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.
@@ -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 via customControls to:', this.useCustomControls);
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: this.config.youtubeNativeControls === true ? 1 : 0,
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.currentYouTubeControlsState = this.config.youtubeNativeControls === true;
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
- const timeDisplay = document.getElementById('uvf-time-display');
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: 350px;
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 = 'AUTO';
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
- let duration = 0;
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:', duration);
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
- this.debugLog('Seeking to position:', time, 'seconds (', Math.round(percent), '%)');
7349
- if (progressFilled && !this.isDragging) {
7017
+ if (progressFilled) {
7350
7018
  progressFilled.style.width = percent + '%';
7351
7019
  }
7352
- if (progressHandle && !this.isDragging) {
7020
+ if (progressHandle) {
7353
7021
  progressHandle.style.left = percent + '%';
7354
- progressHandle.classList.add('dragging');
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))