myetv-player 1.2.0 → 1.3.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.
Files changed (47) hide show
  1. package/css/myetv-player.css +131 -0
  2. package/css/myetv-player.min.css +1 -1
  3. package/dist/myetv-player.js +547 -102
  4. package/dist/myetv-player.min.js +486 -93
  5. package/package.json +35 -17
  6. package/plugins/twitch/myetv-player-twitch-plugin.js +125 -11
  7. package/plugins/vimeo/myetv-player-vimeo.js +80 -49
  8. package/plugins/youtube/README.md +5 -2
  9. package/plugins/youtube/myetv-player-youtube-plugin.js +766 -6
  10. package/.github/workflows/codeql.yml +0 -100
  11. package/.github/workflows/npm-publish.yml +0 -30
  12. package/SECURITY.md +0 -50
  13. package/build.js +0 -195
  14. package/scss/README.md +0 -161
  15. package/scss/_audio-player.scss +0 -21
  16. package/scss/_base.scss +0 -116
  17. package/scss/_controls.scss +0 -204
  18. package/scss/_loading.scss +0 -111
  19. package/scss/_menus.scss +0 -432
  20. package/scss/_mixins.scss +0 -112
  21. package/scss/_poster.scss +0 -8
  22. package/scss/_progress-bar.scss +0 -319
  23. package/scss/_resolution.scss +0 -68
  24. package/scss/_responsive.scss +0 -1368
  25. package/scss/_themes.scss +0 -30
  26. package/scss/_title-overlay.scss +0 -60
  27. package/scss/_tooltips.scss +0 -7
  28. package/scss/_variables.scss +0 -49
  29. package/scss/_video.scss +0 -221
  30. package/scss/_volume.scss +0 -122
  31. package/scss/_watermark.scss +0 -128
  32. package/scss/myetv-player.scss +0 -51
  33. package/scss/package.json +0 -16
  34. package/src/README.md +0 -560
  35. package/src/chapters.js +0 -521
  36. package/src/controls.js +0 -1242
  37. package/src/core.js +0 -1922
  38. package/src/events.js +0 -537
  39. package/src/fullscreen.js +0 -82
  40. package/src/i18n.js +0 -374
  41. package/src/playlist.js +0 -177
  42. package/src/plugins.js +0 -384
  43. package/src/quality.js +0 -963
  44. package/src/streaming.js +0 -346
  45. package/src/subtitles.js +0 -524
  46. package/src/utils.js +0 -65
  47. 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
- }