myetv-player 1.1.2 → 1.1.3

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/build.js CHANGED
@@ -147,14 +147,20 @@ function buildJavaScript() {
147
147
  function minifyJSNative() {
148
148
  const jsFile = './dist/myetv-player.js';
149
149
  const minFile = './dist/myetv-player.min.js';
150
+
150
151
  try {
151
152
  let code = fs.readFileSync(jsFile, 'utf8');
153
+
152
154
  code = code.replace(/\/\*[\s\S]*?\*\//g, '');
153
- code = code.replace(/(^|\s)\/\/.*$/gm, '');
154
- code = code.split('\\n').map(line => line.trim()).filter(line => line.length > 0).join(' ');
155
+ code = code.replace(/^\s*\/\/.*$/gm, '');
156
+
157
+ code = code.replace(/\n\s*\n\s*\n/g, '\n\n');
158
+
159
+ code = code.replace(/ +/g, ' ');
160
+
155
161
  fs.writeFileSync(minFile, code);
156
162
  console.log(`✓ JS (minified native) created: ${minFile}`);
157
- console.log(` File size: ${(code.length / 1024).toFixed(2)} KB`);
163
+ console.log(` File size: ${(code.length / 1024).toFixed(2)} KB`);
158
164
  } catch (err) {
159
165
  console.log('✗ Native JS minification failed:', err.message);
160
166
  }
@@ -4827,10 +4827,10 @@ createCustomSubtitleOverlay() {
4827
4827
  'bottom: 80px;' +
4828
4828
  'left: 50%;' +
4829
4829
  'transform: translateX(-50%);' +
4830
- 'z-index: 5;' +
4830
+ 'z-index: 999;' +
4831
4831
  'color: white;' +
4832
4832
  'font-family: Arial, sans-serif;' +
4833
- 'font-size: clamp(12px, 4vw, 18px);' + // RESPONSIVE font-size
4833
+ 'font-size: clamp(12px, 4vw, 18px);' +
4834
4834
  'font-weight: bold;' +
4835
4835
  'text-align: center;' +
4836
4836
  'text-shadow: 2px 2px 4px rgba(0, 0, 0, 1);' +
@@ -4857,52 +4857,29 @@ createCustomSubtitleOverlay() {
4857
4857
  if (this.options.debug) console.log('✅ Custom subtitle overlay created with responsive settings');
4858
4858
  }
4859
4859
 
4860
- loadCustomSubtitleTracks() {
4861
- var self = this;
4862
- var trackElements = document.querySelectorAll('track[kind="subtitles"], track[kind="captions"]');
4863
- var loadPromises = [];
4864
-
4865
- if (this.options.debug) console.log('📥 Loading ' + trackElements.length + ' subtitle files...');
4866
-
4867
- for (var i = 0; i < trackElements.length; i++) {
4868
- var track = trackElements[i];
4869
-
4870
- (function (trackElement, index) {
4871
- var promise = fetch(trackElement.src)
4872
- .then(function (response) {
4873
- return response.text();
4874
- })
4875
- .then(function (srtText) {
4876
- var subtitles = self.parseCustomSRT(srtText);
4877
- self.customSubtitles.push({
4878
- label: trackElement.label || 'Track ' + (index + 1),
4879
- language: trackElement.srclang || 'unknown',
4880
- subtitles: subtitles
4881
- });
4860
+ customTimeToSeconds(timeString) {
4861
+ if (!timeString) return 0;
4882
4862
 
4883
- if (self.options.debug) {
4884
- console.log('✅ Loaded: ' + trackElement.label + ' (' + subtitles.length + ' subtitles)');
4885
- }
4886
- })
4887
- .catch(function (error) {
4888
- if (self.options.debug) {
4889
- console.error('❌ Error loading ' + trackElement.src + ':', error);
4890
- }
4891
- });
4863
+ var parts = timeString.split(',');
4864
+ if (parts.length !== 2) return 0;
4892
4865
 
4893
- loadPromises.push(promise);
4894
- })(track, i);
4895
- }
4866
+ var time = parts[0];
4867
+ var millis = parts[1];
4896
4868
 
4897
- Promise.all(loadPromises).then(function () {
4898
- if (self.options.debug && self.customSubtitles.length > 0) {
4899
- console.log('✅ All custom subtitle tracks loaded');
4900
- }
4869
+ var timeParts = time.split(':');
4870
+ if (timeParts.length !== 3) return 0;
4901
4871
 
4902
- if (self.options.debug) {
4903
- console.log('📝 Subtitles loaded but NOT auto-enabled - user must activate manually');
4904
- }
4905
- });
4872
+ var hours = parseInt(timeParts[0], 10);
4873
+ var minutes = parseInt(timeParts[1], 10);
4874
+ var seconds = parseInt(timeParts[2], 10);
4875
+ var milliseconds = parseInt(millis, 10);
4876
+
4877
+ if (isNaN(hours) || isNaN(minutes) || isNaN(seconds) || isNaN(milliseconds)) {
4878
+ console.error('❌ customTimeToSeconds failed for:', timeString);
4879
+ return 0;
4880
+ }
4881
+
4882
+ return hours * 3600 + minutes * 60 + seconds + milliseconds / 1000;
4906
4883
  }
4907
4884
 
4908
4885
  parseCustomSRT(srtText) {
@@ -4921,9 +4898,9 @@ parseCustomSRT(srtText) {
4921
4898
  if (timeMatch) {
4922
4899
  var startTime = this.customTimeToSeconds(timeMatch[1]);
4923
4900
  var endTime = this.customTimeToSeconds(timeMatch[2]);
4924
- var text = this.sanitizeSubtitleText(lines.slice(2).join('\n').trim());
4901
+ var text = lines.slice(2).join('\n').trim().replace(/<[^>]*>/g, '');
4925
4902
 
4926
- if (text.length > 0 && startTime < endTime) {
4903
+ if (text && text.length > 0 && startTime < endTime) {
4927
4904
  subtitles.push({
4928
4905
  start: startTime,
4929
4906
  end: endTime,
@@ -4934,20 +4911,97 @@ parseCustomSRT(srtText) {
4934
4911
  }
4935
4912
  }
4936
4913
 
4914
+ if (this.options.debug) console.log('✅ Parsed ' + subtitles.length + ' subtitles');
4937
4915
  return subtitles;
4938
4916
  }
4939
4917
 
4940
- customTimeToSeconds(timeString) {
4941
- var parts = timeString.split(',');
4942
- var time = parts[0];
4943
- var millis = parts[1];
4944
- var timeParts = time.split(':');
4945
- var hours = parseInt(timeParts[0], 10);
4946
- var minutes = parseInt(timeParts[1], 10);
4947
- var seconds = parseInt(timeParts[2], 10);
4948
- var milliseconds = parseInt(millis, 10);
4918
+ loadCustomSubtitleTracks() {
4919
+ var self = this;
4920
+ var tracks = this.video.querySelectorAll('track[kind="subtitles"]');
4921
+ if (tracks.length === 0) return;
4922
+
4923
+ tracks.forEach(function (track, index) {
4924
+ var src = track.getAttribute('src');
4925
+ var label = track.getAttribute('label') || 'Unknown';
4926
+ var srclang = track.getAttribute('srclang') || '';
4927
+
4928
+ // CREA L'OGGETTO PRIMA E AGGIUNGILO SUBITO
4929
+ var trackObj = {
4930
+ label: label,
4931
+ language: srclang,
4932
+ subtitles: [],
4933
+ trackIndex: index
4934
+ };
4935
+ self.customSubtitles.push(trackObj);
4936
+
4937
+ fetch(src)
4938
+ .then(function (response) {
4939
+ return response.text();
4940
+ })
4941
+ .then(function (srtText) {
4942
+ var normalizedText = srtText.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
4943
+ var blocks = normalizedText.trim().split('\n\n');
4944
+
4945
+ for (var i = 0; i < blocks.length; i++) {
4946
+ var block = blocks[i].trim();
4947
+ if (!block) continue;
4948
+ var lines = block.split('\n');
4949
+
4950
+ if (lines.length >= 3) {
4951
+ var timeLine = lines[1].trim();
4952
+ var timeMatch = timeLine.match(/(\d{2}:\d{2}:\d{2},\d{3})\s*-->\s*(\d{2}:\d{2}:\d{2},\d{3})/);
4953
+
4954
+ if (timeMatch) {
4955
+ var startParts = timeMatch[1].split(',');
4956
+ var startTimeParts = startParts[0].split(':');
4957
+ var startTime = parseInt(startTimeParts[0], 10) * 3600 + parseInt(startTimeParts[1], 10) * 60 + parseInt(startTimeParts[2], 10) + parseInt(startParts[1], 10) / 1000;
4958
+
4959
+ var endParts = timeMatch[2].split(',');
4960
+ var endTimeParts = endParts[0].split(':');
4961
+ var endTime = parseInt(endTimeParts[0], 10) * 3600 + parseInt(endTimeParts[1], 10) * 60 + parseInt(endTimeParts[2], 10) + parseInt(endParts[1], 10) / 1000;
4962
+
4963
+ var text = lines.slice(2).join('\n').trim().replace(/<[^>]*>/g, '');
4964
+
4965
+ if (text && text.length > 0 && !isNaN(startTime) && !isNaN(endTime) && startTime < endTime) {
4966
+ trackObj.subtitles.push({
4967
+ start: startTime,
4968
+ end: endTime,
4969
+ text: text
4970
+ });
4971
+ }
4972
+ }
4973
+ }
4974
+ }
4949
4975
 
4950
- return hours * 3600 + minutes * 60 + seconds + milliseconds / 1000;
4976
+ if (self.options.debug) {
4977
+ console.log('✅ Loaded ' + trackObj.subtitles.length + ' subtitles for ' + label);
4978
+ }
4979
+ })
4980
+ .catch(function (error) {
4981
+ console.error('❌ Error loading ' + label + ':', error);
4982
+ });
4983
+ });
4984
+ }
4985
+
4986
+ sanitizeSubtitleText(text) {
4987
+ if (!text) return '';
4988
+
4989
+ // Remove HTML tags
4990
+ var sanitized = text.replace(/<[^>]*>/g, '');
4991
+
4992
+ // Remove styling tags common in SRT files
4993
+ sanitized = sanitized.replace(/{\\.*?}/g, '');
4994
+ sanitized = sanitized.replace(/\\N/g, '\n');
4995
+
4996
+ // Clean up multiple spaces
4997
+ sanitized = sanitized.replace(/\s+/g, ' ').trim();
4998
+
4999
+ // Decode HTML entities if present
5000
+ var tempDiv = document.createElement('div');
5001
+ tempDiv.innerHTML = sanitized;
5002
+ sanitized = tempDiv.textContent || tempDiv.innerText || sanitized;
5003
+
5004
+ return sanitized;
4951
5005
  }
4952
5006
 
4953
5007
  enableCustomSubtitleTrack(trackIndex) {
@@ -5040,28 +5094,39 @@ detectTextTracks() {
5040
5094
  enableSubtitleTrack(trackIndex) {
5041
5095
  if (trackIndex < 0 || trackIndex >= this.textTracks.length) return;
5042
5096
 
5097
+ // Disable all tracks first
5043
5098
  this.disableAllTracks();
5044
5099
 
5100
+ // Enable ONLY the custom subtitle system (not native browser)
5045
5101
  var success = this.enableCustomSubtitleTrack(trackIndex);
5046
5102
 
5047
5103
  if (success) {
5048
5104
  this.currentSubtitleTrack = this.textTracks[trackIndex].track;
5049
5105
  this.subtitlesEnabled = true;
5050
5106
 
5107
+ // Make sure native tracks stay DISABLED
5108
+ if (this.video.textTracks && this.video.textTracks[trackIndex]) {
5109
+ this.video.textTracks[trackIndex].mode = 'disabled'; // Keep native disabled
5110
+ }
5111
+
5051
5112
  this.updateSubtitlesButton();
5052
5113
  this.populateSubtitlesMenu();
5053
5114
 
5054
5115
  if (this.options.debug) {
5055
- console.log('✅ Subtitles enabled: ' + this.textTracks[trackIndex].label);
5116
+ console.log('✅ Custom subtitles enabled:', this.textTracks[trackIndex].label);
5056
5117
  }
5057
5118
 
5058
- // Trigger evento
5119
+ // Trigger subtitle change event
5059
5120
  this.triggerEvent('subtitlechange', {
5060
5121
  enabled: true,
5061
5122
  trackIndex: trackIndex,
5062
5123
  trackLabel: this.textTracks[trackIndex].label,
5063
5124
  trackLanguage: this.textTracks[trackIndex].language
5064
5125
  });
5126
+ } else {
5127
+ if (this.options.debug) {
5128
+ console.error('❌ Failed to enable custom subtitles for track', trackIndex);
5129
+ }
5065
5130
  }
5066
5131
  }
5067
5132
 
@@ -5084,11 +5149,15 @@ disableSubtitles() {
5084
5149
  }
5085
5150
 
5086
5151
  disableAllTracks() {
5087
- if (this.video.textTracks) {
5088
- for (var i = 0; i < this.video.textTracks.length; i++) {
5089
- this.video.textTracks[i].mode = 'hidden';
5090
- }
5152
+ if (!this.video || !this.video.textTracks) return;
5153
+
5154
+ // Disable all native tracks
5155
+ for (var i = 0; i < this.video.textTracks.length; i++) {
5156
+ this.video.textTracks[i].mode = 'hidden';
5091
5157
  }
5158
+
5159
+ // Also disable custom subtitles
5160
+ this.disableCustomSubtitles();
5092
5161
  }
5093
5162
 
5094
5163
  getAvailableSubtitles() {
@@ -5169,25 +5238,61 @@ updateSubtitlesUI() {
5169
5238
  bindSubtitleEvents() {
5170
5239
  var self = this;
5171
5240
 
5241
+ if (this.video.textTracks) {
5242
+ this.isChangingSubtitles = false; // flag to prevent loops
5243
+
5244
+ this.video.textTracks.addEventListener('change', function () {
5245
+ // ignore changes initiated by the player itself
5246
+ if (self.isChangingSubtitles) {
5247
+ return;
5248
+ }
5249
+
5250
+ // only update ui
5251
+ self.updateSubtitlesUI();
5252
+ });
5253
+ }
5254
+
5255
+ // Add timeupdate listener for custom subtitle display
5256
+ this.video.addEventListener('timeupdate', () => {
5257
+ if (this.customSubtitlesEnabled) {
5258
+ this.updateCustomSubtitleDisplay();
5259
+ }
5260
+ });
5261
+
5262
+ // Menu click events
5172
5263
  var subtitlesMenu = this.controls && this.controls.querySelector('.subtitles-menu');
5173
5264
  if (subtitlesMenu) {
5174
5265
  subtitlesMenu.addEventListener('click', function (e) {
5175
- self.handleSubtitlesMenuClick(e);
5266
+ var option = e.target.closest('.subtitles-option');
5267
+ if (!option) return;
5268
+
5269
+ self.isChangingSubtitles = true; // active flag
5270
+
5271
+ var trackIndex = option.getAttribute('data-track');
5272
+ if (trackIndex === 'off') {
5273
+ self.disableSubtitles();
5274
+ } else {
5275
+ self.enableSubtitleTrack(parseInt(trackIndex));
5276
+ }
5277
+
5278
+ setTimeout(function () {
5279
+ self.isChangingSubtitles = false; // disable flag
5280
+ }, 100);
5176
5281
  });
5177
5282
  }
5178
5283
  }
5179
5284
 
5180
-
5181
5285
  handleSubtitlesMenuClick(e) {
5182
- if (!e.target.classList.contains('subtitles-option')) return;
5286
+ var option = e.target.closest('.subtitles-option');
5287
+ if (!option) return; // This prevents button clicks from toggling
5183
5288
 
5184
- var trackData = e.target.getAttribute('data-track');
5289
+ var trackIndex = option.getAttribute('data-track');
5185
5290
 
5186
- if (trackData === 'off') {
5291
+ if (trackIndex === 'off') {
5187
5292
  this.disableSubtitles();
5188
5293
  } else {
5189
- var trackIndex = parseInt(trackData, 10);
5190
- this.enableSubtitleTrack(trackIndex);
5294
+ // Don't check for 'toggle' - just enable the track
5295
+ this.enableSubtitleTrack(parseInt(trackIndex));
5191
5296
  }
5192
5297
 
5193
5298
  this.updateSubtitlesButton();