myetv-player 1.1.1 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myetv-player",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "MYETV Video Player - Modular JavaScript and SCSS Build System",
5
5
  "main": "dist/myetv-player.js",
6
6
  "scripts": {
@@ -34,3 +34,5 @@
34
34
 
35
35
 
36
36
 
37
+
38
+
@@ -54,6 +54,7 @@
54
54
  this.mouseMoveOverlay = null;
55
55
  this.qualityCheckAttempts = 0;
56
56
  this.captionCheckAttempts = 0;
57
+ this.liveStreamChecked = false;
57
58
  this.captionStateCheckInterval = null;
58
59
  this.qualityMonitorInterval = null;
59
60
  this.resizeListenerAdded = false;
@@ -77,6 +78,7 @@
77
78
  { code: 'ar', name: 'Arabic' },
78
79
  { code: 'pt', name: 'Portuguese' },
79
80
  { code: 'ru', name: 'Russian' },
81
+ { code: 'zh', name: 'Chinese' },
80
82
  { code: 'ja', name: 'Japanese' },
81
83
  { code: 'de', name: 'German' },
82
84
  { code: 'fr', name: 'French' },
@@ -1179,10 +1181,11 @@ startBufferMonitoring() {
1179
1181
  // Handle responsive layout for PiP and subtitles buttons
1180
1182
  this.handleResponsiveLayout();
1181
1183
 
1184
+ this.playAttemptTimeout = null;
1185
+
1182
1186
  // Hide PiP from settings menu (separate function, called after responsive layout)
1183
1187
  setTimeout(() => this.hidePipFromSettingsMenuOnly(), 500);
1184
- setTimeout(() => this.hidePipFromSettingsMenuOnly(), 1500);
1185
- setTimeout(() => this.hidePipFromSettingsMenuOnly(), 3000);
1188
+
1186
1189
  // Check if this is a live stream
1187
1190
  setTimeout(() => this.checkIfLiveStream(), 2000);
1188
1191
  setTimeout(() => this.checkIfLiveStream(), 5000);
@@ -1199,13 +1202,9 @@ startBufferMonitoring() {
1199
1202
 
1200
1203
  // Load qualities with multiple attempts
1201
1204
  setTimeout(() => this.loadAvailableQualities(), 500);
1202
- setTimeout(() => this.loadAvailableQualities(), 1000);
1203
- setTimeout(() => this.loadAvailableQualities(), 2000);
1204
1205
 
1205
1206
  // Load captions with multiple attempts
1206
1207
  setTimeout(() => this.loadAvailableCaptions(), 500);
1207
- setTimeout(() => this.loadAvailableCaptions(), 1000);
1208
- setTimeout(() => this.loadAvailableCaptions(), 2000);
1209
1208
 
1210
1209
  if (this.options.quality && this.options.quality !== 'default') {
1211
1210
  setTimeout(() => this.setQuality(this.options.quality), 1000);
@@ -2701,6 +2700,49 @@ startBufferMonitoring() {
2701
2700
  };
2702
2701
  if (this.api.player.options.debug) console.log('[YT Plugin] State:', states[event.data], event.data);
2703
2702
 
2703
+ // Know if video have some problems to start
2704
+ if (event.data === YT.PlayerState.UNSTARTED || event.data === -1) {
2705
+ // start timeout when video is unstarted
2706
+ if (this.playAttemptTimeout) {
2707
+ clearTimeout(this.playAttemptTimeout);
2708
+ }
2709
+
2710
+ this.playAttemptTimeout = setTimeout(() => {
2711
+ if (!this.ytPlayer) return;
2712
+
2713
+ const currentState = this.ytPlayer.getPlayerState();
2714
+
2715
+ // If video is unstrated after timeout, consider it restricted
2716
+ if (currentState === YT.PlayerState.UNSTARTED || currentState === -1) {
2717
+ if (this.api.player.options.debug) {
2718
+ console.log('YT Plugin: Video stuck in UNSTARTED - possibly members-only or restricted');
2719
+ }
2720
+
2721
+ // Trigger ended event
2722
+ this.api.triggerEvent('ended', {
2723
+ reason: 'video_restricted_or_membership',
2724
+ state: currentState
2725
+ });
2726
+
2727
+ // Show poster overlay if present
2728
+ this.showPosterOverlay();
2729
+
2730
+ // Trigger custom event
2731
+ this.api.triggerEvent('youtubeplugin:membershiprestricted', {
2732
+ videoId: this.videoId
2733
+ });
2734
+ }
2735
+ }, 15000); // 15 seconds of timeout
2736
+
2737
+ } else if (event.data === YT.PlayerState.PLAYING ||
2738
+ event.data === YT.PlayerState.BUFFERING) {
2739
+ // Clear the timeout if video starts correctly
2740
+ if (this.playAttemptTimeout) {
2741
+ clearTimeout(this.playAttemptTimeout);
2742
+ this.playAttemptTimeout = null;
2743
+ }
2744
+ }
2745
+
2704
2746
  // Get play/pause icons
2705
2747
  const playIcon = this.api.container.querySelector('.play-icon');
2706
2748
  const pauseIcon = this.api.container.querySelector('.pause-icon');
@@ -3286,6 +3328,12 @@ startBufferMonitoring() {
3286
3328
  dispose() {
3287
3329
  if (this.api.player.options.debug) console.log('[YT Plugin] Disposing');
3288
3330
 
3331
+ // Cleanup timeout
3332
+ if (this.playAttemptTimeout) {
3333
+ clearTimeout(this.playAttemptTimeout);
3334
+ this.playAttemptTimeout = null;
3335
+ }
3336
+
3289
3337
  if (this.timeUpdateInterval) {
3290
3338
  clearInterval(this.timeUpdateInterval);
3291
3339
  this.timeUpdateInterval = null;
@@ -5,360 +5,163 @@
5
5
  @use 'mixins' as *;
6
6
  @use 'variables' as *;
7
7
 
8
- // ===================================
9
- // PREVENT TEXT SELECTION DURING DRAG
10
- // ===================================
11
-
12
- // Disable text selection on all controls when dragging
13
- .controls,
14
- .progress-container,
15
- .progress-bar,
16
- .controls-main,
17
- .controls-left,
18
- .controls-right,
19
- .time-display {
20
- user-select: none; // Prevent text selection
21
- -webkit-user-select: none; // Safari
22
- -moz-user-select: none; // Firefox
23
- -ms-user-select: none; // IE/Edge
24
- }
25
-
26
- // ===================================
27
- // PROGRESS BAR SYSTEM
28
- // ===================================
29
-
30
- .progress-container {
31
- position: relative;
32
- overflow: visible !important; // Allow handle to extend outside the container
33
- padding: 0; // No padding - keeps control bar height normal
34
- margin-bottom: 10px; // Space below instead of padding
35
- display: flex;
36
- align-items: center; // Vertically center the progress bar
37
- cursor: pointer;
38
- }
39
-
40
- .progress-bar {
41
- position: relative;
42
- width: 100%;
43
- height: 4px; // Thin progress bar
44
- background: rgba(255, 255, 255, 0.3); // Semi-transparent background
45
- border-radius: 2px;
46
- overflow: visible !important; // Allow handle to be visible
47
- cursor: pointer;
48
- }
49
-
50
- // Buffer bar (shows buffered/loaded video)
51
- .progress-buffer {
52
- position: absolute;
53
- left: 0;
54
- top: 0;
55
- height: 100%;
56
- background: rgba(255, 255, 255, 0.5);
57
- border-radius: 2px;
58
- pointer-events: none;
59
- z-index: 1; // Below filled bar
60
- }
61
-
62
- // Filled bar (shows watched video progress)
63
- .progress-filled {
8
+ /* CONTROLS CONTAINER - IMPROVED RESPONSIVE DESIGN */
9
+ .controls {
64
10
  position: absolute;
11
+ bottom: 0;
65
12
  left: 0;
66
- top: 0;
67
- height: 100%;
68
- background: var(--player-accent, #ff0000); // Accent color fill
69
- border-radius: 2px;
70
- pointer-events: none;
71
- z-index: 2; // Above buffer, below handle
72
- }
73
-
74
- // ===================================
75
- // PROGRESS HANDLE - BASE STYLES
76
- // ===================================
77
-
78
- .progress-handle {
79
- position: absolute;
80
- top: 50%;
81
- left: 0%;
82
- transform: translate(-50%, -50%); // Center the handle
83
- width: 14px;
84
- height: 14px;
85
- background: var(--player-accent, #ff0000);
86
- cursor: grab; // Indicates draggable
87
- transition: all 0.2s ease; // Smooth transition for size changes
88
- z-index: 10; // Above everything (buffer and filled)
89
- pointer-events: auto; // Ensure it's clickable
90
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); // Subtle shadow for depth
13
+ right: 0;
14
+ background: var(--player-bg-controls);
15
+ padding: var(--player-controls-padding);
16
+ opacity: 0;
17
+ transform: translateY(100%);
18
+ transition: all var(--player-transition-normal);
19
+ z-index: 10;
20
+ min-height: 70px !important;
21
+ box-sizing: border-box;
91
22
  }
92
23
 
93
- // Grabbing cursor when actively dragging
94
- .progress-handle:active {
95
- cursor: grabbing;
24
+ .controls.show {
25
+ opacity: 1;
26
+ transform: translateY(0);
27
+ position: absolute !important;
28
+ bottom: 0 !important;
29
+ z-index: 20 !important;
96
30
  }
97
31
 
98
- // ===================================
99
- // SEEK HANDLE SHAPES
100
- // ===================================
101
-
102
- // Circle - classic round handle (default recommended)
103
- .progress-handle-circle {
104
- border-radius: 50%; // Perfect circle
32
+ /* MAIN CONTROLS - IMPROVED RESPONSIVE LAYOUT */
33
+ .controls-main {
34
+ display: flex;
35
+ justify-content: space-between;
36
+ align-items: center;
37
+ width: 100%;
38
+ min-height: 44px !important;
39
+ flex-shrink: 0;
105
40
  }
106
41
 
107
- // Square - sharp corners
108
- .progress-handle-square {
109
- border-radius: 3px; // Slightly rounded corners
42
+ .controls-left,
43
+ .controls-right {
44
+ display: flex;
45
+ align-items: center;
46
+ gap: 10px;
47
+ flex-shrink: 1;
48
+ min-width: 0;
110
49
  }
111
50
 
112
- // Diamond - rotated square
113
- .progress-handle-diamond {
114
- border-radius: 2px;
115
- transform: translate(-50%, -50%) rotate(45deg); // 45 degree rotation
51
+ /* BUTTONS - IMPROVED RESPONSIVE BEHAVIOR */
52
+ .control-btn {
53
+ background: none;
54
+ border: none;
55
+ color: var(--player-button-color);
56
+ cursor: pointer;
57
+ padding: var(--player-button-padding);
58
+ border-radius: 6px;
59
+ display: flex;
60
+ align-items: center;
61
+ gap: 5px;
62
+ transition: all var(--player-transition-fast);
63
+ font-size: 14px;
64
+ font-weight: 500;
65
+ position: relative;
66
+ flex-shrink: 1;
67
+ min-width: 0;
68
+ white-space: nowrap;
116
69
  }
117
70
 
118
- // Arrow - pointing upward
119
- .progress-handle-arrow {
120
- background: transparent;
121
- width: 0 !important;
122
- height: 0 !important;
123
- border-left: 7px solid transparent;
124
- border-right: 7px solid transparent;
125
- border-bottom: 14px solid var(--player-accent, #ff0000); // Triangle pointing up
126
- border-radius: 0;
127
- box-shadow: none; // No shadow for border-based shapes
71
+ .control-btn:hover {
72
+ background: var(--player-button-hover);
73
+ transform: scale(1.05);
128
74
  }
129
75
 
130
- // Triangle - simple triangle shape
131
- .progress-handle-triangle {
132
- background: transparent;
133
- width: 0 !important;
134
- height: 0 !important;
135
- border-left: 8px solid transparent;
136
- border-right: 8px solid transparent;
137
- border-bottom: 14px solid var(--player-accent, #ff0000);
138
- border-radius: 0;
139
- box-shadow: none;
76
+ .control-btn:active {
77
+ transform: scale(0.95);
78
+ background: var(--player-button-active);
140
79
  }
141
80
 
142
- // Heart - romantic shape using clip-path
143
- .progress-handle-heart {
144
- width: 16px !important;
145
- height: 16px !important;
146
- clip-path: polygon( 50% 15%, 65% 0%, 80% 0%, 95% 15%, 95% 30%, 50% 85%, 5% 30%, 5% 15%, 20% 0%, 35% 0% );
81
+ /* SPECIFIC SUBTITLES BUTTON */
82
+ .subtitles-btn {
83
+ position: relative;
147
84
  }
148
85
 
149
- // Star - five-pointed star using clip-path
150
- .progress-handle-star {
151
- width: 16px !important;
152
- height: 16px !important;
153
- clip-path: polygon( 50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35% );
86
+ /* QUALITY BUTTON WITH DUAL DISPLAY */
87
+ .quality-btn {
88
+ min-height: 36px;
89
+ padding: 6px 8px;
154
90
  }
155
91
 
156
- // None - completely hidden (no visual indicator)
157
- .progress-handle-none {
158
- opacity: 0 !important;
159
- pointer-events: none !important;
92
+ .quality-btn-text {
93
+ display: flex;
94
+ flex-direction: column;
95
+ align-items: center;
96
+ line-height: 1;
160
97
  }
161
98
 
162
- // ===================================
163
- // FORCE HANDLE ALWAYS VISIBLE
164
- // ===================================
165
-
166
- // Override any other rule that hides the handle
167
- .progress-handle {
168
- opacity: 1 !important; // Always visible
99
+ .selected-quality {
100
+ font-size: 14px;
101
+ font-weight: 500;
102
+ color: var(--player-button-color);
169
103
  }
170
104
 
171
- .progress-container .progress-handle {
172
- opacity: 1 !important; // Always visible with higher specificity
105
+ .current-quality {
106
+ font-size: 10px;
107
+ font-weight: 400;
108
+ color: var(--player-text-secondary);
109
+ opacity: 0.8;
110
+ margin-top: 2px;
111
+ line-height: 1;
173
112
  }
174
113
 
175
- // ===================================
176
- // MOBILE TOUCH ENHANCEMENTS
177
- // ===================================
178
-
179
- // Media query for tablets and mobile devices (max width 768px)
180
- @media (max-width: 768px) {
181
-
182
- // Progress bar stays thin (4px)
183
- .progress-bar {
184
- height: 4px; // Keep thin
185
- }
186
-
187
- // Handle with large invisible touch area
188
- .progress-handle {
189
- touch-action: none; // Critical for mobile drag
190
- -webkit-touch-callout: none; // Disable iOS callout
191
- // Add large invisible touch area using pseudo-element
192
- &::before {
193
- content: '';
194
- position: absolute;
195
- top: 50%;
196
- left: 50%;
197
- transform: translate(-50%, -50%);
198
- width: 50px; // Large touch target (50x50px)
199
- height: 50px;
200
- border-radius: 50%;
201
- background: transparent; // Invisible but touchable
202
- z-index: -1; // Behind the visible handle
203
- }
204
- // Scale up when touched/active
205
- &:active {
206
- width: 24px !important; // Grow: 14px -> 24px
207
- height: 24px !important;
208
- box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); // Stronger shadow when active
209
- }
210
- }
211
-
212
- // Adjust shapes when active (touched)
213
- .progress-handle-circle:active {
214
- border-radius: 50%;
215
- }
216
-
217
- .progress-handle-square:active {
218
- border-radius: 5px;
219
- }
220
-
221
- .progress-handle-diamond:active {
222
- border-radius: 4px;
223
- transform: translate(-50%, -50%) rotate(45deg);
224
- }
225
-
226
- .progress-handle-arrow:active {
227
- border-left: 12px solid transparent;
228
- border-right: 12px solid transparent;
229
- border-bottom: 24px solid var(--player-accent, #ff0000);
230
- }
231
-
232
- .progress-handle-triangle:active {
233
- border-left: 13px solid transparent;
234
- border-right: 13px solid transparent;
235
- border-bottom: 24px solid var(--player-accent, #ff0000);
236
- }
237
-
238
- .progress-handle-heart:active,
239
- .progress-handle-star:active {
240
- width: 26px !important;
241
- height: 26px !important;
242
- }
114
+ /* TIME DISPLAY - RESPONSIVE */
115
+ .time-display {
116
+ color: var(--player-text-color);
117
+ font-size: 14px;
118
+ font-weight: 500;
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 5px;
122
+ font-variant-numeric: tabular-nums;
123
+ flex-shrink: 2;
124
+ min-width: 0;
243
125
  }
244
126
 
245
- // Enhanced touch targets for very small screens (phones)
246
- @media (max-width: 480px) {
247
-
248
- // Progress bar stays thin on phones too
249
- .progress-bar {
250
- height: 4px; // Keep thin
251
- }
252
-
253
- .progress-handle {
254
- &::before {
255
- width: 60px; // Extra large touch target on phones
256
- height: 60px;
257
- }
258
- // Even bigger when touched on phones
259
- &:active {
260
- width: 28px !important;
261
- height: 28px !important;
262
- }
263
- }
264
-
265
- .progress-handle-heart:active,
266
- .progress-handle-star:active {
267
- width: 30px !important;
268
- height: 30px !important;
269
- }
127
+ /* ICONS */
128
+ .icon {
129
+ width: var(--player-icon-size);
130
+ height: var(--player-icon-size);
131
+ display: flex;
132
+ align-items: center;
133
+ justify-content: center;
134
+ font-size: 16px;
270
135
  }
271
136
 
272
- // ===================================
273
- // CONTROLS CONTAINER
274
- // ===================================
275
-
276
- /* Main controls container */
277
- .controls {
278
- position: absolute;
279
- bottom: 0;
280
- left: 0;
281
- right: 0;
282
- background: var(--player-bg-controls);
283
- padding: var(--player-controls-padding);
284
- opacity: 0; // Hidden by default
285
- transform: translateY(100%); // Slide out below
286
- transition: all var(--player-transition-normal);
287
- z-index: 10;
288
- min-height: 70px !important;
289
- box-sizing: border-box;
137
+ .hidden {
138
+ display: none !important;
290
139
  }
291
140
 
292
- /* Controls visible state */
293
- .controls.show {
294
- opacity: 1; // Fully visible
295
- transform: translateY(0); // Slide in
296
- position: absolute !important;
297
- bottom: 0 !important;
298
- z-index: 20 !important; // Above other elements
141
+ /* BRAND LOGO RESPONSIVE */
142
+ .controls-right .brand-logo {
143
+ height: 44px;
144
+ max-width: 120px;
145
+ object-fit: contain;
146
+ margin-right: 10px;
147
+ pointer-events: auto;
148
+ opacity: 0.8;
149
+ transition: opacity var(--player-transition-fast);
150
+ order: -1;
151
+ flex-shrink: 1;
299
152
  }
300
153
 
301
- // ===================================
302
- // TOUCH EVENT FIXES FOR MOBILE
303
- // ===================================
304
-
305
- // Prevent default touch behavior on progress bar
306
- .progress-container,
307
- .progress-bar,
308
- .progress-handle {
309
- touch-action: none; // Disable browser's default touch gestures
310
- -webkit-touch-callout: none; // Disable callout on iOS
154
+ .controls-right .brand-logo:hover {
155
+ opacity: 1;
311
156
  }
312
157
 
313
- // ===================================
314
- // ENCODING BADGE - Video in encoding
315
- // ===================================
316
-
317
- /* Badge for video in encoding (duration Infinity/NaN) */
318
- .encoding-badge {
158
+ .controls-right .brand-logo-link {
159
+ order: -1;
160
+ margin-right: 10px;
319
161
  display: inline-block;
320
- background: rgba(128, 128, 128, 0.8); // Grigio semi-trasparente
321
- color: white;
322
- padding: 2px 8px;
323
- border-radius: 4px;
324
- font-size: 11px;
325
- font-weight: 500;
326
- text-transform: uppercase;
327
- letter-spacing: 0.5px;
328
- white-space: nowrap;
329
- backdrop-filter: blur(4px);
330
- border: 1px solid rgba(255, 255, 255, 0.2);
331
- animation: encoding-pulse 2s ease-in-out infinite;
332
- }
333
-
334
- /* Class for the container when shows the badge */
335
- .time-display .encoding-state {
336
- display: flex;
337
- align-items: center;
338
- }
339
-
340
- /* animation for the badge */
341
- @keyframes encoding-pulse {
342
- 0%, 100% {
343
- opacity: 0.8;
344
- }
345
-
346
- 50% {
347
- opacity: 1;
348
- }
349
- }
350
-
351
- // Responsive for badge encoding
352
- @media (max-width: 480px) {
353
- .encoding-badge {
354
- font-size: 9px;
355
- padding: 1px 6px;
356
- }
162
+ text-decoration: none;
357
163
  }
358
164
 
359
- @media (max-width: 350px) {
360
- .encoding-badge {
361
- font-size: 8px;
362
- padding: 1px 4px;
363
- }
165
+ .controls-right .brand-logo-link .brand-logo {
166
+ margin-right: 0;
364
167
  }