unified-video-framework 1.4.261 → 1.4.263
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/package.json +1 -1
- package/packages/core/dist/interfaces/IVideoPlayer.d.ts +0 -1
- package/packages/core/dist/interfaces/IVideoPlayer.d.ts.map +1 -1
- package/packages/core/dist/interfaces.d.ts +0 -1
- package/packages/core/dist/interfaces.d.ts.map +1 -1
- package/packages/core/src/interfaces/IVideoPlayer.ts +0 -3
- package/packages/core/src/interfaces.ts +0 -1
- package/packages/web/dist/WebPlayer.d.ts +0 -10
- package/packages/web/dist/WebPlayer.d.ts.map +1 -1
- package/packages/web/dist/WebPlayer.js +19 -349
- package/packages/web/dist/WebPlayer.js.map +1 -1
- package/packages/web/dist/react/WebPlayerView.d.ts +1 -1
- package/packages/web/dist/react/WebPlayerView.d.ts.map +1 -1
- package/packages/web/dist/react/WebPlayerView.js +1 -2
- package/packages/web/dist/react/WebPlayerView.js.map +1 -1
- package/packages/web/src/WebPlayer.ts +44 -477
- package/packages/web/src/react/WebPlayerView.tsx +2 -5
|
@@ -94,9 +94,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
94
94
|
this.youtubePlayerReady = false;
|
|
95
95
|
this.youtubeIframe = null;
|
|
96
96
|
this.youtubeTimeTrackingInterval = null;
|
|
97
|
-
this.isYouTubeLive = false;
|
|
98
|
-
this.useYouTubeNativeControls = false;
|
|
99
|
-
this.currentYouTubeControlsState = null;
|
|
100
97
|
this.clickToUnmuteHandler = null;
|
|
101
98
|
}
|
|
102
99
|
debugLog(message, ...args) {
|
|
@@ -118,11 +115,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
118
115
|
console.log('WebPlayer.initialize called with config:', config);
|
|
119
116
|
if (config && config.customControls !== undefined) {
|
|
120
117
|
this.useCustomControls = config.customControls;
|
|
121
|
-
console.log('Custom controls set
|
|
122
|
-
}
|
|
123
|
-
else if (config && config.controls !== undefined) {
|
|
124
|
-
this.useCustomControls = config.controls;
|
|
125
|
-
console.log('Custom controls set via controls to:', this.useCustomControls);
|
|
118
|
+
console.log('Custom controls set to:', this.useCustomControls);
|
|
126
119
|
}
|
|
127
120
|
if (config && config.settings) {
|
|
128
121
|
console.log('Settings config found:', config.settings);
|
|
@@ -856,13 +849,8 @@ export class WebPlayer extends BasePlayer {
|
|
|
856
849
|
if (this.video && metadata.thumbnail) {
|
|
857
850
|
this.video.poster = metadata.thumbnail;
|
|
858
851
|
}
|
|
859
|
-
this.updateMetadataUI();
|
|
860
852
|
await this.createYouTubePlayer(videoId);
|
|
861
|
-
setTimeout(() => {
|
|
862
|
-
this.updateMetadataUI();
|
|
863
|
-
}, 1000);
|
|
864
853
|
this.debugLog('✅ YouTube video loaded successfully');
|
|
865
|
-
this.debugLog('YouTube video title:', metadata.title);
|
|
866
854
|
}
|
|
867
855
|
catch (error) {
|
|
868
856
|
this.debugError('Failed to load YouTube video:', error);
|
|
@@ -901,7 +889,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
901
889
|
width: '100%',
|
|
902
890
|
height: '100%',
|
|
903
891
|
playerVars: {
|
|
904
|
-
controls:
|
|
892
|
+
controls: 0,
|
|
905
893
|
disablekb: 0,
|
|
906
894
|
fs: 0,
|
|
907
895
|
iv_load_policy: 3,
|
|
@@ -918,8 +906,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
918
906
|
onError: (event) => this.onYouTubePlayerError(event)
|
|
919
907
|
}
|
|
920
908
|
});
|
|
921
|
-
this.
|
|
922
|
-
this.debugLog('YouTube player created with controls:', this.currentYouTubeControlsState);
|
|
909
|
+
this.debugLog('YouTube player created');
|
|
923
910
|
}
|
|
924
911
|
async loadYouTubeAPI() {
|
|
925
912
|
return new Promise((resolve) => {
|
|
@@ -959,12 +946,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
959
946
|
if (this.config.muted) {
|
|
960
947
|
this.youtubePlayer.mute();
|
|
961
948
|
}
|
|
962
|
-
this.detectYouTubeLiveStatus();
|
|
963
|
-
this.getYouTubeVideoTitle();
|
|
964
|
-
setTimeout(() => {
|
|
965
|
-
this.updateMetadataUI();
|
|
966
|
-
this.updateControlsVisibility();
|
|
967
|
-
}, 500);
|
|
968
949
|
}
|
|
969
950
|
this.startYouTubeTimeTracking();
|
|
970
951
|
this.emit('onReady');
|
|
@@ -1001,10 +982,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
1001
982
|
case window.YT.PlayerState.CUED:
|
|
1002
983
|
this.state.duration = this.youtubePlayer.getDuration();
|
|
1003
984
|
this.updateYouTubeUI('cued');
|
|
1004
|
-
setTimeout(() => {
|
|
1005
|
-
this.detectYouTubeLiveStatus();
|
|
1006
|
-
this.updateControlsVisibility();
|
|
1007
|
-
}, 500);
|
|
1008
985
|
break;
|
|
1009
986
|
}
|
|
1010
987
|
}
|
|
@@ -1055,255 +1032,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
1055
1032
|
details: { errorCode }
|
|
1056
1033
|
});
|
|
1057
1034
|
}
|
|
1058
|
-
getYouTubeVideoTitle() {
|
|
1059
|
-
if (!this.youtubePlayer || !this.youtubePlayerReady)
|
|
1060
|
-
return;
|
|
1061
|
-
try {
|
|
1062
|
-
const videoData = this.youtubePlayer.getVideoData();
|
|
1063
|
-
if (videoData && videoData.title) {
|
|
1064
|
-
this.debugLog('Got YouTube title from player API:', videoData.title);
|
|
1065
|
-
if (this.source && this.source.metadata) {
|
|
1066
|
-
this.source.metadata.title = videoData.title;
|
|
1067
|
-
}
|
|
1068
|
-
this.updateMetadataUI();
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
catch (error) {
|
|
1072
|
-
this.debugWarn('Could not get YouTube video title from API:', error);
|
|
1073
|
-
this.getYouTubeVideoTitleFromOEmbed();
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
detectYouTubeLiveStatus() {
|
|
1077
|
-
if (!this.youtubePlayer || !this.youtubePlayerReady)
|
|
1078
|
-
return;
|
|
1079
|
-
try {
|
|
1080
|
-
const videoData = this.youtubePlayer.getVideoData();
|
|
1081
|
-
this.isYouTubeLive = videoData?.isLive || false;
|
|
1082
|
-
this.useYouTubeNativeControls = this.config.youtubeNativeControls === true;
|
|
1083
|
-
this.debugLog('YouTube Live status:', {
|
|
1084
|
-
isLive: this.isYouTubeLive,
|
|
1085
|
-
useNativeControls: this.useYouTubeNativeControls,
|
|
1086
|
-
videoId: videoData?.video_id
|
|
1087
|
-
});
|
|
1088
|
-
}
|
|
1089
|
-
catch (error) {
|
|
1090
|
-
this.debugWarn('Could not detect YouTube Live status:', error);
|
|
1091
|
-
try {
|
|
1092
|
-
const duration = this.youtubePlayer.getDuration();
|
|
1093
|
-
this.isYouTubeLive = !duration || duration === 0;
|
|
1094
|
-
this.useYouTubeNativeControls = this.config.youtubeNativeControls === true;
|
|
1095
|
-
this.debugLog('YouTube Live detected via duration check:', {
|
|
1096
|
-
duration,
|
|
1097
|
-
isLive: this.isYouTubeLive,
|
|
1098
|
-
useNativeControls: this.useYouTubeNativeControls
|
|
1099
|
-
});
|
|
1100
|
-
}
|
|
1101
|
-
catch (e) {
|
|
1102
|
-
this.debugWarn('Could not check YouTube duration for Live detection:', e);
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
updateControlsVisibility() {
|
|
1107
|
-
const controlsContainer = document.getElementById('uvf-controls');
|
|
1108
|
-
if (!controlsContainer) {
|
|
1109
|
-
this.debugWarn('Controls container not found, looking for .uvf-controls-bar');
|
|
1110
|
-
const controlsBar = this.playerWrapper?.querySelector('.uvf-controls-bar');
|
|
1111
|
-
if (!controlsBar) {
|
|
1112
|
-
this.debugWarn('Controls bar not found either, cannot update controls visibility');
|
|
1113
|
-
return;
|
|
1114
|
-
}
|
|
1115
|
-
const controlsContainerFallback = controlsBar;
|
|
1116
|
-
if (this.youtubePlayer && this.useYouTubeNativeControls) {
|
|
1117
|
-
controlsContainerFallback.style.display = 'none';
|
|
1118
|
-
const videoContainer = this.playerWrapper?.querySelector('.uvf-video-container');
|
|
1119
|
-
if (videoContainer) {
|
|
1120
|
-
const allControls = videoContainer.querySelectorAll('.uvf-top-gradient, .uvf-controls-gradient, .uvf-top-bar, .uvf-center-play-container, .uvf-shortcut-indicator');
|
|
1121
|
-
allControls.forEach(el => el.style.display = 'none');
|
|
1122
|
-
}
|
|
1123
|
-
if (this.currentYouTubeControlsState !== true) {
|
|
1124
|
-
this.recreateYouTubePlayerWithNativeControls();
|
|
1125
|
-
this.currentYouTubeControlsState = true;
|
|
1126
|
-
}
|
|
1127
|
-
this.debugLog('✅ YouTube native controls enabled', {
|
|
1128
|
-
isLive: this.isYouTubeLive,
|
|
1129
|
-
reason: this.config.youtubeNativeControls === true ? 'Explicitly enabled in config' : 'Live stream detected'
|
|
1130
|
-
});
|
|
1131
|
-
}
|
|
1132
|
-
else {
|
|
1133
|
-
controlsContainerFallback.style.display = 'flex';
|
|
1134
|
-
const videoContainer = this.playerWrapper?.querySelector('.uvf-video-container');
|
|
1135
|
-
if (videoContainer) {
|
|
1136
|
-
const allControls = videoContainer.querySelectorAll('.uvf-top-gradient, .uvf-controls-gradient, .uvf-top-bar, .uvf-center-play-container, .uvf-shortcut-indicator');
|
|
1137
|
-
allControls.forEach(el => el.style.display = '');
|
|
1138
|
-
}
|
|
1139
|
-
if (this.currentYouTubeControlsState !== false) {
|
|
1140
|
-
this.recreateYouTubePlayerWithoutNativeControls();
|
|
1141
|
-
this.currentYouTubeControlsState = false;
|
|
1142
|
-
}
|
|
1143
|
-
this.debugLog('✅ Custom controls enabled for YouTube video');
|
|
1144
|
-
}
|
|
1145
|
-
return;
|
|
1146
|
-
}
|
|
1147
|
-
if (this.youtubePlayer && this.useYouTubeNativeControls) {
|
|
1148
|
-
controlsContainer.style.display = 'none';
|
|
1149
|
-
if (this.currentYouTubeControlsState !== true) {
|
|
1150
|
-
this.recreateYouTubePlayerWithNativeControls();
|
|
1151
|
-
this.currentYouTubeControlsState = true;
|
|
1152
|
-
}
|
|
1153
|
-
this.debugLog('✅ YouTube native controls enabled', {
|
|
1154
|
-
isLive: this.isYouTubeLive,
|
|
1155
|
-
reason: this.config.youtubeNativeControls === true ? 'Explicitly enabled in config' : 'Live stream detected'
|
|
1156
|
-
});
|
|
1157
|
-
}
|
|
1158
|
-
else {
|
|
1159
|
-
controlsContainer.style.display = 'flex';
|
|
1160
|
-
if (this.currentYouTubeControlsState !== false) {
|
|
1161
|
-
this.recreateYouTubePlayerWithoutNativeControls();
|
|
1162
|
-
this.currentYouTubeControlsState = false;
|
|
1163
|
-
}
|
|
1164
|
-
this.debugLog('✅ Custom controls enabled for YouTube video');
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
recreateYouTubePlayerWithNativeControls() {
|
|
1168
|
-
if (!this.source?.metadata?.videoId)
|
|
1169
|
-
return;
|
|
1170
|
-
const videoId = this.source.metadata.videoId;
|
|
1171
|
-
const currentTime = this.youtubePlayer?.getCurrentTime() || 0;
|
|
1172
|
-
const container = this.playerWrapper || this.video?.parentElement;
|
|
1173
|
-
if (!container)
|
|
1174
|
-
return;
|
|
1175
|
-
if (this.youtubePlayer) {
|
|
1176
|
-
this.youtubePlayer.destroy();
|
|
1177
|
-
}
|
|
1178
|
-
const existingContainer = container.querySelector(`#youtube-player-${videoId}`);
|
|
1179
|
-
if (existingContainer) {
|
|
1180
|
-
existingContainer.remove();
|
|
1181
|
-
}
|
|
1182
|
-
const iframeContainer = document.createElement('div');
|
|
1183
|
-
iframeContainer.id = `youtube-player-${videoId}`;
|
|
1184
|
-
iframeContainer.style.cssText = `
|
|
1185
|
-
position: absolute;
|
|
1186
|
-
top: 0;
|
|
1187
|
-
left: 0;
|
|
1188
|
-
width: 100%;
|
|
1189
|
-
height: 100%;
|
|
1190
|
-
z-index: 1;
|
|
1191
|
-
`;
|
|
1192
|
-
container.appendChild(iframeContainer);
|
|
1193
|
-
this.youtubePlayer = new window.YT.Player(iframeContainer.id, {
|
|
1194
|
-
videoId: videoId,
|
|
1195
|
-
width: '100%',
|
|
1196
|
-
height: '100%',
|
|
1197
|
-
playerVars: {
|
|
1198
|
-
autoplay: this.config.autoPlay ? 1 : 0,
|
|
1199
|
-
controls: 1,
|
|
1200
|
-
modestbranding: 1,
|
|
1201
|
-
rel: 0,
|
|
1202
|
-
showinfo: 0,
|
|
1203
|
-
iv_load_policy: 3,
|
|
1204
|
-
playsinline: 1,
|
|
1205
|
-
start: Math.floor(currentTime)
|
|
1206
|
-
},
|
|
1207
|
-
events: {
|
|
1208
|
-
onReady: () => {
|
|
1209
|
-
this.youtubePlayerReady = true;
|
|
1210
|
-
this.debugLog('YouTube player with native controls ready');
|
|
1211
|
-
this.emit('onReady');
|
|
1212
|
-
},
|
|
1213
|
-
onStateChange: (event) => this.onYouTubePlayerStateChange(event),
|
|
1214
|
-
onError: (event) => this.onYouTubePlayerError(event)
|
|
1215
|
-
}
|
|
1216
|
-
});
|
|
1217
|
-
}
|
|
1218
|
-
recreateYouTubePlayerWithoutNativeControls() {
|
|
1219
|
-
if (!this.source?.metadata?.videoId)
|
|
1220
|
-
return;
|
|
1221
|
-
const videoId = this.source.metadata.videoId;
|
|
1222
|
-
const currentTime = this.youtubePlayer?.getCurrentTime() || 0;
|
|
1223
|
-
const container = this.playerWrapper || this.video?.parentElement;
|
|
1224
|
-
if (!container)
|
|
1225
|
-
return;
|
|
1226
|
-
if (this.youtubePlayer) {
|
|
1227
|
-
this.youtubePlayer.destroy();
|
|
1228
|
-
}
|
|
1229
|
-
const existingContainer = container.querySelector(`#youtube-player-${videoId}`);
|
|
1230
|
-
if (existingContainer) {
|
|
1231
|
-
existingContainer.remove();
|
|
1232
|
-
}
|
|
1233
|
-
const iframeContainer = document.createElement('div');
|
|
1234
|
-
iframeContainer.id = `youtube-player-${videoId}`;
|
|
1235
|
-
iframeContainer.style.cssText = `
|
|
1236
|
-
position: absolute;
|
|
1237
|
-
top: 0;
|
|
1238
|
-
left: 0;
|
|
1239
|
-
width: 100%;
|
|
1240
|
-
height: 100%;
|
|
1241
|
-
z-index: 1;
|
|
1242
|
-
`;
|
|
1243
|
-
container.appendChild(iframeContainer);
|
|
1244
|
-
this.youtubePlayer = new window.YT.Player(iframeContainer.id, {
|
|
1245
|
-
videoId: videoId,
|
|
1246
|
-
width: '100%',
|
|
1247
|
-
height: '100%',
|
|
1248
|
-
playerVars: {
|
|
1249
|
-
autoplay: this.config.autoPlay ? 1 : 0,
|
|
1250
|
-
controls: 0,
|
|
1251
|
-
disablekb: 0,
|
|
1252
|
-
fs: 0,
|
|
1253
|
-
iv_load_policy: 3,
|
|
1254
|
-
modestbranding: 1,
|
|
1255
|
-
rel: 0,
|
|
1256
|
-
showinfo: 0,
|
|
1257
|
-
playsinline: 1,
|
|
1258
|
-
start: Math.floor(currentTime)
|
|
1259
|
-
},
|
|
1260
|
-
events: {
|
|
1261
|
-
onReady: () => {
|
|
1262
|
-
this.youtubePlayerReady = true;
|
|
1263
|
-
this.debugLog('YouTube player without native controls ready');
|
|
1264
|
-
this.emit('onReady');
|
|
1265
|
-
},
|
|
1266
|
-
onStateChange: (event) => this.onYouTubePlayerStateChange(event),
|
|
1267
|
-
onError: (event) => this.onYouTubePlayerError(event)
|
|
1268
|
-
}
|
|
1269
|
-
});
|
|
1270
|
-
}
|
|
1271
|
-
toggleYouTubeControls(useNative = !this.useYouTubeNativeControls) {
|
|
1272
|
-
if (!this.youtubePlayer) {
|
|
1273
|
-
this.debugWarn('Cannot toggle YouTube controls - no YouTube player active');
|
|
1274
|
-
return;
|
|
1275
|
-
}
|
|
1276
|
-
this.useYouTubeNativeControls = useNative;
|
|
1277
|
-
this.config.youtubeNativeControls = useNative;
|
|
1278
|
-
this.updateControlsVisibility();
|
|
1279
|
-
this.debugLog('YouTube controls toggled:', {
|
|
1280
|
-
useNative: this.useYouTubeNativeControls,
|
|
1281
|
-
isLive: this.isYouTubeLive
|
|
1282
|
-
});
|
|
1283
|
-
this.showNotification(`YouTube Controls: ${this.useYouTubeNativeControls ? 'Native' : 'Custom'}`);
|
|
1284
|
-
}
|
|
1285
|
-
async getYouTubeVideoTitleFromOEmbed() {
|
|
1286
|
-
if (!this.source?.metadata?.videoId)
|
|
1287
|
-
return;
|
|
1288
|
-
try {
|
|
1289
|
-
const videoId = this.source.metadata.videoId;
|
|
1290
|
-
const oembedUrl = `https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${videoId}&format=json`;
|
|
1291
|
-
const response = await fetch(oembedUrl);
|
|
1292
|
-
if (response.ok) {
|
|
1293
|
-
const data = await response.json();
|
|
1294
|
-
if (data.title) {
|
|
1295
|
-
this.debugLog('Got YouTube title from oembed API:', data.title);
|
|
1296
|
-
if (this.source && this.source.metadata) {
|
|
1297
|
-
this.source.metadata.title = data.title;
|
|
1298
|
-
}
|
|
1299
|
-
this.updateMetadataUI();
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
catch (error) {
|
|
1304
|
-
this.debugWarn('Could not get YouTube title from oembed API:', error);
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
1035
|
startYouTubeTimeTracking() {
|
|
1308
1036
|
if (this.youtubeTimeTrackingInterval) {
|
|
1309
1037
|
clearInterval(this.youtubeTimeTrackingInterval);
|
|
@@ -1337,18 +1065,12 @@ export class WebPlayer extends BasePlayer {
|
|
|
1337
1065
|
const progressHandle = document.getElementById('uvf-progress-handle');
|
|
1338
1066
|
if (progressHandle && !this.isDragging) {
|
|
1339
1067
|
progressHandle.style.left = percent + '%';
|
|
1340
|
-
progressHandle.classList.remove('dragging');
|
|
1341
1068
|
}
|
|
1342
1069
|
const progressBuffered = document.getElementById('uvf-progress-buffered');
|
|
1343
1070
|
if (progressBuffered) {
|
|
1344
1071
|
progressBuffered.style.width = buffered + '%';
|
|
1345
1072
|
}
|
|
1346
|
-
|
|
1347
|
-
if (timeDisplay) {
|
|
1348
|
-
const currentTimeStr = this.formatTime(currentTime);
|
|
1349
|
-
const durationStr = this.formatTime(duration);
|
|
1350
|
-
timeDisplay.textContent = `${currentTimeStr} / ${durationStr}`;
|
|
1351
|
-
}
|
|
1073
|
+
this.updateTimeDisplay();
|
|
1352
1074
|
}
|
|
1353
1075
|
loadScript(src) {
|
|
1354
1076
|
return new Promise((resolve, reject) => {
|
|
@@ -1683,27 +1405,12 @@ export class WebPlayer extends BasePlayer {
|
|
|
1683
1405
|
updateTimeTooltip(e) {
|
|
1684
1406
|
const progressBar = document.getElementById('uvf-progress-bar');
|
|
1685
1407
|
const tooltip = document.getElementById('uvf-time-tooltip');
|
|
1686
|
-
if (!progressBar || !tooltip)
|
|
1687
|
-
return;
|
|
1688
|
-
let duration = 0;
|
|
1689
|
-
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
1690
|
-
try {
|
|
1691
|
-
duration = this.youtubePlayer.getDuration() || 0;
|
|
1692
|
-
}
|
|
1693
|
-
catch (error) {
|
|
1694
|
-
this.debugWarn('Error getting YouTube duration for tooltip:', error);
|
|
1695
|
-
return;
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
else if (this.video) {
|
|
1699
|
-
duration = this.video.duration || 0;
|
|
1700
|
-
}
|
|
1701
|
-
if (!duration || !isFinite(duration))
|
|
1408
|
+
if (!progressBar || !tooltip || !this.video)
|
|
1702
1409
|
return;
|
|
1703
1410
|
const rect = progressBar.getBoundingClientRect();
|
|
1704
1411
|
const x = Math.max(0, Math.min(e.clientX - rect.left, rect.width));
|
|
1705
1412
|
const percent = (x / rect.width);
|
|
1706
|
-
const time = percent * duration;
|
|
1413
|
+
const time = percent * this.video.duration;
|
|
1707
1414
|
tooltip.textContent = this.formatTime(time);
|
|
1708
1415
|
tooltip.style.left = `${x}px`;
|
|
1709
1416
|
tooltip.classList.add('visible');
|
|
@@ -4112,29 +3819,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
4112
3819
|
}
|
|
4113
3820
|
|
|
4114
3821
|
.uvf-accordion-item.expanded .uvf-accordion-content {
|
|
4115
|
-
max-height:
|
|
4116
|
-
overflow-y: auto;
|
|
4117
|
-
-webkit-overflow-scrolling: touch;
|
|
4118
|
-
}
|
|
4119
|
-
|
|
4120
|
-
/* Special handling for quality accordion with many options */
|
|
4121
|
-
.uvf-accordion-item.expanded .uvf-accordion-content[data-section="quality"] {
|
|
4122
|
-
max-height: 400px;
|
|
4123
|
-
}
|
|
4124
|
-
|
|
4125
|
-
/* Scrollbar styling for accordion content */
|
|
4126
|
-
.uvf-accordion-content::-webkit-scrollbar {
|
|
4127
|
-
width: 4px;
|
|
4128
|
-
}
|
|
4129
|
-
.uvf-accordion-content::-webkit-scrollbar-track {
|
|
4130
|
-
background: transparent;
|
|
4131
|
-
}
|
|
4132
|
-
.uvf-accordion-content::-webkit-scrollbar-thumb {
|
|
4133
|
-
background: rgba(255,255,255,0.3);
|
|
4134
|
-
border-radius: 2px;
|
|
4135
|
-
}
|
|
4136
|
-
.uvf-accordion-content::-webkit-scrollbar-thumb:hover {
|
|
4137
|
-
background: rgba(255,255,255,0.5);
|
|
3822
|
+
max-height: 250px;
|
|
4138
3823
|
}
|
|
4139
3824
|
|
|
4140
3825
|
/* Settings options within accordion */
|
|
@@ -6200,7 +5885,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
6200
5885
|
const qualityBadge = document.createElement('div');
|
|
6201
5886
|
qualityBadge.className = 'uvf-quality-badge';
|
|
6202
5887
|
qualityBadge.id = 'uvf-quality-badge';
|
|
6203
|
-
qualityBadge.textContent = '
|
|
5888
|
+
qualityBadge.textContent = 'HD';
|
|
6204
5889
|
rightControls.appendChild(qualityBadge);
|
|
6205
5890
|
this.debugLog('Settings config check:', this.settingsConfig);
|
|
6206
5891
|
this.debugLog('Settings enabled:', this.settingsConfig.enabled);
|
|
@@ -7314,27 +6999,11 @@ export class WebPlayer extends BasePlayer {
|
|
|
7314
6999
|
const progressBar = document.querySelector('.uvf-progress-bar');
|
|
7315
7000
|
const progressFilled = document.getElementById('uvf-progress-filled');
|
|
7316
7001
|
const progressHandle = document.getElementById('uvf-progress-handle');
|
|
7317
|
-
if (!progressBar)
|
|
7002
|
+
if (!progressBar || !this.video)
|
|
7318
7003
|
return;
|
|
7319
|
-
|
|
7320
|
-
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
7321
|
-
try {
|
|
7322
|
-
duration = this.youtubePlayer.getDuration() || 0;
|
|
7323
|
-
}
|
|
7324
|
-
catch (error) {
|
|
7325
|
-
this.debugWarn('Error getting YouTube duration for seeking:', error);
|
|
7326
|
-
return;
|
|
7327
|
-
}
|
|
7328
|
-
}
|
|
7329
|
-
else if (this.video) {
|
|
7330
|
-
duration = this.video.duration;
|
|
7331
|
-
}
|
|
7332
|
-
else {
|
|
7333
|
-
this.debugWarn('No video source available for seeking');
|
|
7334
|
-
return;
|
|
7335
|
-
}
|
|
7004
|
+
const duration = this.video.duration;
|
|
7336
7005
|
if (!isFinite(duration) || isNaN(duration) || duration <= 0) {
|
|
7337
|
-
this.debugWarn('Invalid video duration, cannot seek via progress bar
|
|
7006
|
+
this.debugWarn('Invalid video duration, cannot seek via progress bar');
|
|
7338
7007
|
return;
|
|
7339
7008
|
}
|
|
7340
7009
|
const rect = progressBar.getBoundingClientRect();
|
|
@@ -7345,18 +7014,19 @@ export class WebPlayer extends BasePlayer {
|
|
|
7345
7014
|
this.debugWarn('Calculated seek time is invalid:', time);
|
|
7346
7015
|
return;
|
|
7347
7016
|
}
|
|
7348
|
-
|
|
7349
|
-
if (progressFilled && !this.isDragging) {
|
|
7017
|
+
if (progressFilled) {
|
|
7350
7018
|
progressFilled.style.width = percent + '%';
|
|
7351
7019
|
}
|
|
7352
|
-
if (progressHandle
|
|
7020
|
+
if (progressHandle) {
|
|
7353
7021
|
progressHandle.style.left = percent + '%';
|
|
7354
|
-
|
|
7022
|
+
if (this.isDragging) {
|
|
7023
|
+
progressHandle.classList.add('dragging');
|
|
7024
|
+
}
|
|
7025
|
+
else {
|
|
7026
|
+
progressHandle.classList.remove('dragging');
|
|
7027
|
+
}
|
|
7355
7028
|
}
|
|
7356
7029
|
this.seek(time);
|
|
7357
|
-
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
7358
|
-
this.emit('onSeeking');
|
|
7359
|
-
}
|
|
7360
7030
|
}
|
|
7361
7031
|
formatTime(seconds) {
|
|
7362
7032
|
if (!seconds || isNaN(seconds))
|