myetv-player 1.2.0 → 1.4.0
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/css/myetv-player.css +242 -168
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +638 -203
- package/dist/myetv-player.min.js +548 -170
- package/package.json +35 -16
- package/plugins/twitch/myetv-player-twitch-plugin.js +125 -11
- package/plugins/vimeo/myetv-player-vimeo.js +80 -49
- package/plugins/youtube/README.md +5 -2
- package/plugins/youtube/myetv-player-youtube-plugin.js +766 -6
- package/.github/workflows/codeql.yml +0 -100
- package/.github/workflows/npm-publish.yml +0 -30
- package/SECURITY.md +0 -50
- package/build.js +0 -195
- package/scss/README.md +0 -161
- package/scss/_audio-player.scss +0 -21
- package/scss/_base.scss +0 -116
- package/scss/_controls.scss +0 -204
- package/scss/_loading.scss +0 -111
- package/scss/_menus.scss +0 -432
- package/scss/_mixins.scss +0 -112
- package/scss/_poster.scss +0 -8
- package/scss/_progress-bar.scss +0 -319
- package/scss/_resolution.scss +0 -68
- package/scss/_responsive.scss +0 -1368
- package/scss/_themes.scss +0 -30
- package/scss/_title-overlay.scss +0 -60
- package/scss/_tooltips.scss +0 -7
- package/scss/_variables.scss +0 -49
- package/scss/_video.scss +0 -221
- package/scss/_volume.scss +0 -122
- package/scss/_watermark.scss +0 -128
- package/scss/myetv-player.scss +0 -51
- package/scss/package.json +0 -16
- package/src/README.md +0 -560
- package/src/chapters.js +0 -521
- package/src/controls.js +0 -1242
- package/src/core.js +0 -1922
- package/src/events.js +0 -537
- package/src/fullscreen.js +0 -82
- package/src/i18n.js +0 -374
- package/src/playlist.js +0 -177
- package/src/plugins.js +0 -384
- package/src/quality.js +0 -963
- package/src/streaming.js +0 -346
- package/src/subtitles.js +0 -524
- package/src/utils.js +0 -65
- package/src/watermark.js +0 -246
package/src/plugins.js
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
/* Plugins Module for MYETV Video Player
|
|
2
|
-
* Plugin system for extensible player functionality
|
|
3
|
-
* Created by https://www.myetv.tv https://oskarcosimo.com
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// ===================================================================
|
|
7
|
-
// GLOBAL CODE - Will be placed OUTSIDE the class by build script
|
|
8
|
-
// ===================================================================
|
|
9
|
-
// NOTE: This section will be extracted by the build script
|
|
10
|
-
// and placed outside the class definition
|
|
11
|
-
|
|
12
|
-
/* GLOBAL_START */
|
|
13
|
-
// Global plugin registry
|
|
14
|
-
if (!window.MYETVPlayerPlugins) {
|
|
15
|
-
window.MYETVPlayerPlugins = {};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Register a plugin globally
|
|
20
|
-
* @param {String} name - Plugin name
|
|
21
|
-
* @param {Function|Object} plugin - Plugin constructor or factory function
|
|
22
|
-
*/
|
|
23
|
-
function registerPlugin(name, plugin) {
|
|
24
|
-
if (window.MYETVPlayerPlugins[name]) {
|
|
25
|
-
console.warn(`Plugin "${name}" is already registered. Overwriting...`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
window.MYETVPlayerPlugins[name] = plugin;
|
|
29
|
-
|
|
30
|
-
if (typeof console !== 'undefined') {
|
|
31
|
-
console.log(`🔌 Plugin "${name}" registered globally`);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Export registerPlugin as a global function
|
|
36
|
-
window.registerMYETVPlugin = registerPlugin;
|
|
37
|
-
/* GLOBAL_END */
|
|
38
|
-
|
|
39
|
-
// ===================================================================
|
|
40
|
-
// CLASS METHODS - Will be placed INSIDE the class
|
|
41
|
-
// ===================================================================
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Initialize plugin system for player instance
|
|
45
|
-
* This method should be called in the player constructor
|
|
46
|
-
*/
|
|
47
|
-
initializePluginSystem() {
|
|
48
|
-
// Plugin instances storage
|
|
49
|
-
this.plugins = {};
|
|
50
|
-
|
|
51
|
-
// Plugin hooks for lifecycle events
|
|
52
|
-
this.pluginHooks = {
|
|
53
|
-
'beforeInit': [],
|
|
54
|
-
'afterInit': [],
|
|
55
|
-
'beforePlay': [],
|
|
56
|
-
'afterPlay': [],
|
|
57
|
-
'beforePause': [],
|
|
58
|
-
'afterPause': [],
|
|
59
|
-
'beforeQualityChange': [],
|
|
60
|
-
'afterQualityChange': [],
|
|
61
|
-
'beforeDestroy': [],
|
|
62
|
-
'afterDestroy': []
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
if (this.options.debug) {
|
|
66
|
-
console.log('🔌 Plugin system initialized');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Load plugins specified in options
|
|
70
|
-
if (this.options.plugins && typeof this.options.plugins === 'object') {
|
|
71
|
-
this.loadPlugins(this.options.plugins);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Load multiple plugins from options
|
|
77
|
-
* @param {Object} pluginsConfig - Object with plugin names as keys and options as values
|
|
78
|
-
*/
|
|
79
|
-
loadPlugins(pluginsConfig) {
|
|
80
|
-
for (const pluginName in pluginsConfig) {
|
|
81
|
-
if (pluginsConfig.hasOwnProperty(pluginName)) {
|
|
82
|
-
const pluginOptions = pluginsConfig[pluginName];
|
|
83
|
-
this.usePlugin(pluginName, pluginOptions);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Use (initialize) a plugin on this player instance
|
|
90
|
-
* @param {String} name - Plugin name
|
|
91
|
-
* @param {Object} options - Plugin options
|
|
92
|
-
* @returns {Object|null} Plugin instance or null if failed
|
|
93
|
-
*/
|
|
94
|
-
usePlugin(name, options = {}) {
|
|
95
|
-
// Check if plugin is registered
|
|
96
|
-
if (!window.MYETVPlayerPlugins[name]) {
|
|
97
|
-
console.error(`🔌 Plugin "${name}" is not registered. Please load the plugin file first.`);
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Check if plugin is already initialized
|
|
102
|
-
if (this.plugins[name]) {
|
|
103
|
-
console.warn(`🔌 Plugin "${name}" is already initialized on this player`);
|
|
104
|
-
return this.plugins[name];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
try {
|
|
108
|
-
const PluginClass = window.MYETVPlayerPlugins[name];
|
|
109
|
-
|
|
110
|
-
// Trigger before plugin setup event
|
|
111
|
-
this.triggerPluginEvent('beforepluginsetup', name, options);
|
|
112
|
-
this.triggerPluginEvent(`beforepluginsetup:${name}`, name, options);
|
|
113
|
-
|
|
114
|
-
// Initialize plugin
|
|
115
|
-
let pluginInstance;
|
|
116
|
-
|
|
117
|
-
if (typeof PluginClass === 'function') {
|
|
118
|
-
// Plugin is a constructor or factory function
|
|
119
|
-
pluginInstance = new PluginClass(this, options);
|
|
120
|
-
} else if (typeof PluginClass === 'object' && typeof PluginClass.create === 'function') {
|
|
121
|
-
// Plugin is an object with create method
|
|
122
|
-
pluginInstance = PluginClass.create(this, options);
|
|
123
|
-
} else {
|
|
124
|
-
throw new Error(`Invalid plugin format for "${name}"`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Store plugin instance
|
|
128
|
-
this.plugins[name] = pluginInstance;
|
|
129
|
-
|
|
130
|
-
// Call plugin setup method if exists
|
|
131
|
-
if (typeof pluginInstance.setup === 'function') {
|
|
132
|
-
pluginInstance.setup();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Trigger after plugin setup event
|
|
136
|
-
this.triggerPluginEvent('pluginsetup', name, options);
|
|
137
|
-
this.triggerPluginEvent(`pluginsetup:${name}`, name, options);
|
|
138
|
-
|
|
139
|
-
if (this.options.debug) {
|
|
140
|
-
console.log(`🔌 Plugin "${name}" initialized successfully`);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return pluginInstance;
|
|
144
|
-
|
|
145
|
-
} catch (error) {
|
|
146
|
-
console.error(`🔌 Failed to initialize plugin "${name}":`, error);
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Get a plugin instance
|
|
153
|
-
* @param {String} name - Plugin name
|
|
154
|
-
* @returns {Object|null} Plugin instance or null
|
|
155
|
-
*/
|
|
156
|
-
getPlugin(name) {
|
|
157
|
-
return this.plugins[name] || null;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Check if a plugin is loaded
|
|
162
|
-
* @param {String} name - Plugin name
|
|
163
|
-
* @returns {Boolean}
|
|
164
|
-
*/
|
|
165
|
-
hasPlugin(name) {
|
|
166
|
-
return !!this.plugins[name];
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Remove a plugin from this player instance
|
|
171
|
-
* @param {String} name - Plugin name
|
|
172
|
-
* @returns {Boolean} Success status
|
|
173
|
-
*/
|
|
174
|
-
removePlugin(name) {
|
|
175
|
-
if (!this.plugins[name]) {
|
|
176
|
-
console.warn(`🔌 Plugin "${name}" is not initialized on this player`);
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
try {
|
|
181
|
-
const plugin = this.plugins[name];
|
|
182
|
-
|
|
183
|
-
// Call plugin dispose method if exists
|
|
184
|
-
if (typeof plugin.dispose === 'function') {
|
|
185
|
-
plugin.dispose();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Remove plugin instance
|
|
189
|
-
delete this.plugins[name];
|
|
190
|
-
|
|
191
|
-
if (this.options.debug) {
|
|
192
|
-
console.log(`🔌 Plugin "${name}" removed successfully`);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return true;
|
|
196
|
-
|
|
197
|
-
} catch (error) {
|
|
198
|
-
console.error(`🔌 Failed to remove plugin "${name}":`, error);
|
|
199
|
-
return false;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Trigger plugin-specific event
|
|
205
|
-
* @param {String} eventType - Event type
|
|
206
|
-
* @param {String} pluginName - Plugin name
|
|
207
|
-
* @param {Object} data - Event data
|
|
208
|
-
*/
|
|
209
|
-
triggerPluginEvent(eventType, pluginName, data = {}) {
|
|
210
|
-
// Use existing event system
|
|
211
|
-
this.triggerEvent(eventType, {
|
|
212
|
-
pluginName: pluginName,
|
|
213
|
-
...data
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Register a hook for plugin lifecycle
|
|
219
|
-
* @param {String} hookName - Hook name
|
|
220
|
-
* @param {Function} callback - Callback function
|
|
221
|
-
*/
|
|
222
|
-
registerPluginHook(hookName, callback) {
|
|
223
|
-
if (!this.pluginHooks[hookName]) {
|
|
224
|
-
this.pluginHooks[hookName] = [];
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
this.pluginHooks[hookName].push(callback);
|
|
228
|
-
|
|
229
|
-
if (this.options.debug) {
|
|
230
|
-
console.log(`🔌 Hook registered: ${hookName}`);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Execute plugin hooks
|
|
236
|
-
* @param {String} hookName - Hook name
|
|
237
|
-
* @param {Object} data - Data to pass to hook callbacks
|
|
238
|
-
*/
|
|
239
|
-
executePluginHooks(hookName, data = {}) {
|
|
240
|
-
if (!this.pluginHooks[hookName] || this.pluginHooks[hookName].length === 0) {
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
this.pluginHooks[hookName].forEach(callback => {
|
|
245
|
-
try {
|
|
246
|
-
callback(data);
|
|
247
|
-
} catch (error) {
|
|
248
|
-
console.error(`🔌 Error executing hook "${hookName}":`, error);
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Dispose all plugins
|
|
255
|
-
*/
|
|
256
|
-
disposeAllPlugins() {
|
|
257
|
-
const pluginNames = Object.keys(this.plugins);
|
|
258
|
-
|
|
259
|
-
pluginNames.forEach(name => {
|
|
260
|
-
this.removePlugin(name);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
if (this.options.debug) {
|
|
264
|
-
console.log('🔌 All plugins disposed');
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Get all active plugins
|
|
270
|
-
* @returns {Object}
|
|
271
|
-
*/
|
|
272
|
-
getActivePlugins() {
|
|
273
|
-
return { ...this.plugins };
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Get plugin API
|
|
278
|
-
* @returns {Object}
|
|
279
|
-
*/
|
|
280
|
-
getPluginAPI() {
|
|
281
|
-
return {
|
|
282
|
-
player: this,
|
|
283
|
-
video: this.video,
|
|
284
|
-
container: this.container,
|
|
285
|
-
controls: this.controls,
|
|
286
|
-
play: () => this.play(),
|
|
287
|
-
pause: () => this.pause(),
|
|
288
|
-
togglePlayPause: () => this.togglePlayPause(),
|
|
289
|
-
getCurrentTime: () => this.getCurrentTime(),
|
|
290
|
-
setCurrentTime: (time) => this.setCurrentTime(time),
|
|
291
|
-
getDuration: () => this.getDuration(),
|
|
292
|
-
getVolume: () => this.getVolume(),
|
|
293
|
-
setVolume: (volume) => this.setVolume(volume),
|
|
294
|
-
addEventListener: (eventType, callback) => this.addEventListener(eventType, callback),
|
|
295
|
-
removeEventListener: (eventType, callback) => this.removeEventListener(eventType, callback),
|
|
296
|
-
triggerEvent: (eventType, data) => this.triggerEvent(eventType, data),
|
|
297
|
-
registerHook: (hookName, callback) => this.registerPluginHook(hookName, callback),
|
|
298
|
-
addControlButton: (button) => this.addPluginControlButton(button),
|
|
299
|
-
removeControlButton: (buttonId) => this.removePluginControlButton(buttonId),
|
|
300
|
-
getQualities: () => this.getQualities(),
|
|
301
|
-
setQuality: (quality) => this.setQuality(quality),
|
|
302
|
-
options: this.options,
|
|
303
|
-
debug: (message) => {
|
|
304
|
-
if (this.options.debug) {
|
|
305
|
-
console.log('🔌 Plugin debug:', message);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Add a custom control button for plugins
|
|
313
|
-
* @param {Object} buttonConfig
|
|
314
|
-
* @returns {HTMLElement|null}
|
|
315
|
-
*/
|
|
316
|
-
addPluginControlButton(buttonConfig) {
|
|
317
|
-
if (!this.controls) {
|
|
318
|
-
console.error('🔌 Controls not available');
|
|
319
|
-
return null;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
const {
|
|
323
|
-
id,
|
|
324
|
-
icon,
|
|
325
|
-
tooltip,
|
|
326
|
-
position = 'right',
|
|
327
|
-
onClick,
|
|
328
|
-
className = ''
|
|
329
|
-
} = buttonConfig;
|
|
330
|
-
|
|
331
|
-
const button = document.createElement('button');
|
|
332
|
-
button.id = id || `plugin-btn-${Date.now()}`;
|
|
333
|
-
button.className = `control-btn plugin-control-btn ${className}`;
|
|
334
|
-
button.setAttribute('aria-label', tooltip || 'Plugin button');
|
|
335
|
-
button.setAttribute('title', tooltip || '');
|
|
336
|
-
|
|
337
|
-
if (icon) {
|
|
338
|
-
button.innerHTML = icon;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if (onClick && typeof onClick === 'function') {
|
|
342
|
-
button.addEventListener('click', (e) => {
|
|
343
|
-
e.stopPropagation();
|
|
344
|
-
onClick(e, this);
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const targetContainer = position === 'left'
|
|
349
|
-
? this.controls.querySelector('.controls-left')
|
|
350
|
-
: this.controls.querySelector('.controls-right');
|
|
351
|
-
|
|
352
|
-
if (targetContainer) {
|
|
353
|
-
targetContainer.appendChild(button);
|
|
354
|
-
|
|
355
|
-
if (this.options.debug) {
|
|
356
|
-
console.log(`🔌 Plugin control button added: ${button.id}`);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
return button;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
return null;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Remove a plugin control button
|
|
367
|
-
* @param {String} buttonId
|
|
368
|
-
* @returns {Boolean}
|
|
369
|
-
*/
|
|
370
|
-
removePluginControlButton(buttonId) {
|
|
371
|
-
const button = document.getElementById(buttonId);
|
|
372
|
-
|
|
373
|
-
if (button) {
|
|
374
|
-
button.remove();
|
|
375
|
-
|
|
376
|
-
if (this.options.debug) {
|
|
377
|
-
console.log(`🔌 Plugin control button removed: ${buttonId}`);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
return true;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
return false;
|
|
384
|
-
}
|