@therealtinhtute/baroiplayer 1.0.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 (244) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +384 -0
  3. package/dist/context/media.js +2 -0
  4. package/dist/context/media.js.map +1 -0
  5. package/dist/context/media.mjs +15 -0
  6. package/dist/context/media.mjs.map +1 -0
  7. package/dist/context/store.js +2 -0
  8. package/dist/context/store.js.map +1 -0
  9. package/dist/context/store.mjs +5 -0
  10. package/dist/context/store.mjs.map +1 -0
  11. package/dist/context-BMteAJDN.js +1140 -0
  12. package/dist/context-BMteAJDN.js.map +1 -0
  13. package/dist/context-DCJ_scmO.cjs +23 -0
  14. package/dist/context-DCJ_scmO.cjs.map +1 -0
  15. package/dist/core-events-B5W_j8yU.js +480 -0
  16. package/dist/core-events-B5W_j8yU.js.map +1 -0
  17. package/dist/core-events-CN0-Vhhq.cjs +2 -0
  18. package/dist/core-events-CN0-Vhhq.cjs.map +1 -0
  19. package/dist/core-plugins-Bq9KLany.js +696 -0
  20. package/dist/core-plugins-Bq9KLany.js.map +1 -0
  21. package/dist/core-plugins-CPDSHMiQ.cjs +2 -0
  22. package/dist/core-plugins-CPDSHMiQ.cjs.map +1 -0
  23. package/dist/core.js +37 -0
  24. package/dist/core.js.map +1 -0
  25. package/dist/core.mjs +1217 -0
  26. package/dist/core.mjs.map +1 -0
  27. package/dist/enhanced-components-DHv0MFvG.js +1073 -0
  28. package/dist/enhanced-components-DHv0MFvG.js.map +1 -0
  29. package/dist/enhanced-components-DTIObgB7.cjs +2 -0
  30. package/dist/enhanced-components-DTIObgB7.cjs.map +1 -0
  31. package/dist/hooks-C_r8wexn.cjs +4 -0
  32. package/dist/hooks-C_r8wexn.cjs.map +1 -0
  33. package/dist/hooks-Da2wVXlF.js +1630 -0
  34. package/dist/hooks-Da2wVXlF.js.map +1 -0
  35. package/dist/index.css +1 -0
  36. package/dist/index.js +112 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/index.mjs +6126 -0
  39. package/dist/index.mjs.map +1 -0
  40. package/dist/minimal-components-DSq5sQpy.js +2002 -0
  41. package/dist/minimal-components-DSq5sQpy.js.map +1 -0
  42. package/dist/minimal-components-DflWiihN.cjs +2 -0
  43. package/dist/minimal-components-DflWiihN.cjs.map +1 -0
  44. package/dist/minimal-components.css +1 -0
  45. package/dist/mona-loading.gif +0 -0
  46. package/dist/performance-monitor-CUW6f5ll.cjs +2 -0
  47. package/dist/performance-monitor-CUW6f5ll.cjs.map +1 -0
  48. package/dist/performance-monitor-rMW1RgV3.js +302 -0
  49. package/dist/performance-monitor-rMW1RgV3.js.map +1 -0
  50. package/dist/utils-BnscpYYd.js +2798 -0
  51. package/dist/utils-BnscpYYd.js.map +1 -0
  52. package/dist/utils-D_czS_0K.cjs +9 -0
  53. package/dist/utils-D_czS_0K.cjs.map +1 -0
  54. package/dist/utils.js +2 -0
  55. package/dist/utils.js.map +1 -0
  56. package/dist/utils.mjs +7 -0
  57. package/dist/utils.mjs.map +1 -0
  58. package/package.json +114 -0
  59. package/src/adapters/videojs-adapter.tsx +470 -0
  60. package/src/assets/mona-loading.gif +0 -0
  61. package/src/components/AnimateLoading.tsx +115 -0
  62. package/src/components/LoadingState.tsx +248 -0
  63. package/src/components/accessibility/keyboard-help-overlay.tsx +213 -0
  64. package/src/components/audio-player.tsx +85 -0
  65. package/src/components/basic/index.ts +37 -0
  66. package/src/components/enhanced/advanced-features.tsx +316 -0
  67. package/src/components/enhanced/debug-panel.tsx +422 -0
  68. package/src/components/enhanced/enhanced-controls.tsx +600 -0
  69. package/src/components/enhanced/enhanced-media-player.tsx +509 -0
  70. package/src/components/enhanced/error-handling.tsx +345 -0
  71. package/src/components/enhanced/index.ts +39 -0
  72. package/src/components/enhanced/media-player-enhanced.tsx +349 -0
  73. package/src/components/examples/basic-video-player.tsx +55 -0
  74. package/src/components/examples/custom-controls-example.tsx +63 -0
  75. package/src/components/examples/enhanced-controls-example.tsx +114 -0
  76. package/src/components/examples/enhanced-media-player-example.tsx +293 -0
  77. package/src/components/examples/loading-states-demo.tsx +142 -0
  78. package/src/components/examples/react-19-demo.tsx +381 -0
  79. package/src/components/examples/volume-orientation-demo.tsx +114 -0
  80. package/src/components/icon-demo.tsx +209 -0
  81. package/src/components/icons/index.tsx +166 -0
  82. package/src/components/icons/svg-icons/ArrowLeftIcon.tsx +18 -0
  83. package/src/components/icons/svg-icons/ArrowRightIcon.tsx +18 -0
  84. package/src/components/icons/svg-icons/AudioIcon.tsx +22 -0
  85. package/src/components/icons/svg-icons/BackwardIcon.tsx +12 -0
  86. package/src/components/icons/svg-icons/CameraIcon.tsx +19 -0
  87. package/src/components/icons/svg-icons/CheckIcon.tsx +19 -0
  88. package/src/components/icons/svg-icons/EnablePiPIcon.tsx +17 -0
  89. package/src/components/icons/svg-icons/ForwardIcon.tsx +12 -0
  90. package/src/components/icons/svg-icons/FullscreenEnterIcon.tsx +23 -0
  91. package/src/components/icons/svg-icons/FullscreenExitIcon.tsx +23 -0
  92. package/src/components/icons/svg-icons/LoadingIcon.tsx +32 -0
  93. package/src/components/icons/svg-icons/PauseIcon.tsx +23 -0
  94. package/src/components/icons/svg-icons/PlayIcon.tsx +21 -0
  95. package/src/components/icons/svg-icons/PlaybackSpeedIcon.tsx +23 -0
  96. package/src/components/icons/svg-icons/QualityIcon.tsx +21 -0
  97. package/src/components/icons/svg-icons/SettingsIcon.tsx +12 -0
  98. package/src/components/icons/svg-icons/SliderIcon.tsx +21 -0
  99. package/src/components/icons/svg-icons/SubtitleIcon.tsx +21 -0
  100. package/src/components/icons/svg-icons/SubtitleOffIcon.tsx +25 -0
  101. package/src/components/icons/svg-icons/UnPiPIcon.tsx +17 -0
  102. package/src/components/icons/svg-icons/VolumeMutedIcon.tsx +16 -0
  103. package/src/components/icons/svg-icons/VolumeOneIcon.tsx +22 -0
  104. package/src/components/icons/svg-icons/VolumeThreeIcon.tsx +16 -0
  105. package/src/components/icons/svg-icons/VolumeTwoIcon.tsx +16 -0
  106. package/src/components/legacy.tsx +93 -0
  107. package/src/components/media-metadata-display.tsx +100 -0
  108. package/src/components/media-player-audio.tsx +39 -0
  109. package/src/components/media-player-controls.tsx +226 -0
  110. package/src/components/media-player-error.tsx +163 -0
  111. package/src/components/media-player-fullscreen.tsx +109 -0
  112. package/src/components/media-player-hls.tsx +111 -0
  113. package/src/components/media-player-loading.tsx +76 -0
  114. package/src/components/media-player-play.tsx +75 -0
  115. package/src/components/media-player-root.tsx +340 -0
  116. package/src/components/media-player-seek.tsx +168 -0
  117. package/src/components/media-player-time.tsx +99 -0
  118. package/src/components/media-player-tooltip.tsx +58 -0
  119. package/src/components/media-player-video.tsx +39 -0
  120. package/src/components/media-player-volume.tsx +155 -0
  121. package/src/components/media-player.tsx +257 -0
  122. package/src/components/media-suspense.tsx +362 -0
  123. package/src/components/player-settings-form.tsx +163 -0
  124. package/src/components/react-player-wrapper.tsx +651 -0
  125. package/src/components/simple-video-player.tsx +60 -0
  126. package/src/components/ui/enhanced-seek-bar.tsx +235 -0
  127. package/src/components/ui/fullscreen-button.tsx +60 -0
  128. package/src/components/ui/media-resource-preloader.tsx +395 -0
  129. package/src/components/ui/play-button.tsx +107 -0
  130. package/src/components/ui/seek-bar.tsx +161 -0
  131. package/src/components/ui/time-display.tsx +40 -0
  132. package/src/components/ui/volume-control.tsx +143 -0
  133. package/src/components/unified/base-media-player.tsx +246 -0
  134. package/src/components/unified/media-player.tsx +75 -0
  135. package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +561 -0
  136. package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +552 -0
  137. package/src/components/variants/minimal/MinimalControls.tsx +142 -0
  138. package/src/components/variants/minimal/MinimalLoading.tsx +32 -0
  139. package/src/components/variants/minimal/MinimalMediaPlayer.tsx +315 -0
  140. package/src/components/variants/minimal/MinimalOverlay.tsx +64 -0
  141. package/src/components/variants/minimal/MinimalPlayButton.tsx +65 -0
  142. package/src/components/variants/minimal/MinimalSeekBar.tsx +150 -0
  143. package/src/components/variants/minimal/MinimalVolumeControl.tsx +80 -0
  144. package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +210 -0
  145. package/src/components/variants/minimal/components/CenterPlayButton.tsx +22 -0
  146. package/src/components/variants/minimal/components/ControlBar.tsx +146 -0
  147. package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +361 -0
  148. package/src/components/variants/minimal/components/PlaybackControls.tsx +51 -0
  149. package/src/components/variants/minimal/components/RightControls.tsx +173 -0
  150. package/src/components/variants/minimal/components/SeekBar.tsx +131 -0
  151. package/src/components/variants/minimal/components/SettingsDropdown.tsx +70 -0
  152. package/src/components/variants/minimal/components/SubtitleDisplay.tsx +21 -0
  153. package/src/components/variants/minimal/components/TimeDisplay.tsx +18 -0
  154. package/src/components/variants/minimal/components/VideoElement.tsx +40 -0
  155. package/src/components/variants/minimal/components/VolumeControl.tsx +217 -0
  156. package/src/components/variants/minimal/index.ts +23 -0
  157. package/src/components/video-player.tsx +100 -0
  158. package/src/context/error-handling.ts +394 -0
  159. package/src/context/media-context.tsx +208 -0
  160. package/src/context/media-provider.tsx +265 -0
  161. package/src/context/media-store.ts +379 -0
  162. package/src/context/persistence.ts +453 -0
  163. package/src/core/events/event-system.ts +442 -0
  164. package/src/core/events/hooks.ts +302 -0
  165. package/src/core/events/index.ts +22 -0
  166. package/src/core/events/middleware.ts +269 -0
  167. package/src/core/index.ts +22 -0
  168. package/src/core/optimization/bundle-optimizer.tsx +308 -0
  169. package/src/core/performance/cicd.ts +96 -0
  170. package/src/core/performance/index.ts +38 -0
  171. package/src/core/performance/media-loading-optimizer.ts +538 -0
  172. package/src/core/performance/performance-budgets.ts +432 -0
  173. package/src/core/performance/performance-monitor.tsx +476 -0
  174. package/src/core/performance/performance-testing.ts +459 -0
  175. package/src/core/plugins/base-plugin.ts +224 -0
  176. package/src/core/plugins/enhanced-plugin-system.ts +411 -0
  177. package/src/core/plugins/examples/analytics-plugin.ts +242 -0
  178. package/src/core/plugins/index.ts +39 -0
  179. package/src/core/plugins/registry.ts +327 -0
  180. package/src/core/plugins/types.ts +159 -0
  181. package/src/core/plugins/utils.ts +316 -0
  182. package/src/core/progressive-loading.tsx +322 -0
  183. package/src/core/providers/enhanced-hls-provider.ts +339 -0
  184. package/src/core/providers/service-provider.tsx +168 -0
  185. package/src/core/utils.tsx +38 -0
  186. package/src/features/media-session/media-session-manager.ts +429 -0
  187. package/src/features/picture-in-picture/pip-manager.ts +429 -0
  188. package/src/features/playlist/playlist-manager.ts +606 -0
  189. package/src/features/subtitles/subtitle-manager.ts +441 -0
  190. package/src/features/subtitles/subtitle-parser.ts +280 -0
  191. package/src/features/thumbnails/thumbnail-generator.ts +519 -0
  192. package/src/hooks/accessibility/index.ts +27 -0
  193. package/src/hooks/accessibility/use-accessibility-preferences.ts +188 -0
  194. package/src/hooks/accessibility/use-focus-management.ts +176 -0
  195. package/src/hooks/accessibility/use-keyboard-shortcuts.ts +144 -0
  196. package/src/hooks/accessibility/use-screen-reader.ts +182 -0
  197. package/src/hooks/core/index.ts +47 -0
  198. package/src/hooks/legacy.ts +27 -0
  199. package/src/hooks/use-enhanced-media-player.ts +468 -0
  200. package/src/hooks/use-intelligent-preloading.ts +358 -0
  201. package/src/hooks/use-keyboard-controls.ts +115 -0
  202. package/src/hooks/use-media-actions.ts +175 -0
  203. package/src/hooks/use-media-metadata.ts +89 -0
  204. package/src/hooks/use-media-optimistic.ts +270 -0
  205. package/src/hooks/use-media-player.ts +312 -0
  206. package/src/hooks/use-media-state.ts +190 -0
  207. package/src/hooks/use-memory-optimization.ts +358 -0
  208. package/src/hooks/use-optimistic-controls.ts +92 -0
  209. package/src/hooks/use-optimized-media.ts +263 -0
  210. package/src/hooks/use-touch-gestures.ts +417 -0
  211. package/src/hooks/useEnhancedSubtitles.ts +258 -0
  212. package/src/hooks/useKeyboardShortcuts.ts +74 -0
  213. package/src/hooks/useMediaControls.ts +52 -0
  214. package/src/hooks/useScreenshot.ts +57 -0
  215. package/src/hooks/useSubtitles.ts +91 -0
  216. package/src/hooks/useVideoPlayer.ts +232 -0
  217. package/src/icons/components/FullscreenIcon.tsx +37 -0
  218. package/src/icons/components/SettingsIcon.tsx +38 -0
  219. package/src/icons/components/animated/LoadingIcon.tsx +43 -0
  220. package/src/icons/components/animated/PlayPauseIcon.tsx +50 -0
  221. package/src/icons/components/media/PauseIcon.tsx +39 -0
  222. package/src/icons/components/media/PlayIcon.tsx +38 -0
  223. package/src/icons/components/volume/VolumeIcon.tsx +39 -0
  224. package/src/icons/components/volume/VolumeOffIcon.tsx +39 -0
  225. package/src/icons/index.ts +56 -0
  226. package/src/icons/provider.tsx +64 -0
  227. package/src/icons/types.ts +40 -0
  228. package/src/index-enhanced.ts +35 -0
  229. package/src/index-legacy.ts +326 -0
  230. package/src/index.css +102 -0
  231. package/src/index.ts +216 -0
  232. package/src/lib/deprecation.ts +51 -0
  233. package/src/lib/format-time.ts +37 -0
  234. package/src/lib/index.ts +3 -0
  235. package/src/lib/utils.ts +6 -0
  236. package/src/styles/globals.css +462 -0
  237. package/src/styles/minimal-player.css +589 -0
  238. package/src/styles/pixel-art.css +46 -0
  239. package/src/styles/videojs.css +100 -0
  240. package/src/test/setup.ts +79 -0
  241. package/src/types/events.ts +47 -0
  242. package/src/types/formats.ts +95 -0
  243. package/src/types/index.ts +190 -0
  244. package/src/types/videojs-plugins.d.ts +14 -0
@@ -0,0 +1,411 @@
1
+ /**
2
+ * Enhanced Plugin System with Video.js-inspired hooks architecture
3
+ * Provides middleware-based extensibility while maintaining backward compatibility
4
+ */
5
+
6
+ import { BasePlugin } from './base-plugin';
7
+ import { MediaPlayerInstance, MediaPlayerConfig } from '../../types';
8
+
9
+ // Plugin hooks interface inspired by Video.js architecture
10
+ export interface MediaPluginHooks {
11
+ /** Called before player setup, can modify configuration */
12
+ beforeSetup?: (element: HTMLElement, options: MediaPlayerConfig) => MediaPlayerConfig;
13
+ /** Called during player setup */
14
+ setup?: (player: MediaPlayerInstance) => MediaPlayerInstance | void;
15
+ /** Called when player is ready */
16
+ ready?: (player: MediaPlayerInstance) => void;
17
+ /** Called when media source is loaded */
18
+ sourceLoaded?: (player: MediaPlayerInstance, source: string) => void;
19
+ /** Called on playback state changes */
20
+ playbackChange?: (player: MediaPlayerInstance, isPlaying: boolean) => void;
21
+ /** Called on error events */
22
+ error?: (player: MediaPlayerInstance, error: MediaError) => MediaError | void;
23
+ /** Called before player disposal */
24
+ beforeDispose?: (player: MediaPlayerInstance) => void;
25
+ /** Called during quality changes */
26
+ qualityChange?: (player: MediaPlayerInstance, quality: number) => void;
27
+ /** Called during volume changes */
28
+ volumeChange?: (player: MediaPlayerInstance, volume: number) => void;
29
+ /** Called during fullscreen changes */
30
+ fullscreenChange?: (player: MediaPlayerInstance, isFullscreen: boolean) => void;
31
+ }
32
+
33
+ // Enhanced plugin with hooks support
34
+ export abstract class EnhancedMediaPlugin extends BasePlugin {
35
+ protected hooks: Partial<MediaPluginHooks> = {};
36
+ protected priority: number = 0;
37
+ protected middleware?: PluginMiddleware;
38
+
39
+ constructor(name: string, config: any = {}) {
40
+ super(name, config);
41
+ this.priority = config.priority || 0;
42
+ this.setupHooks();
43
+ }
44
+
45
+ /**
46
+ * Override to setup plugin-specific hooks
47
+ */
48
+ protected setupHooks(): void {
49
+ // Override in subclasses
50
+ }
51
+
52
+ /**
53
+ * Register a hook
54
+ */
55
+ public registerHook<K extends keyof MediaPluginHooks>(
56
+ hookType: K,
57
+ handler: MediaPluginHooks[K]
58
+ ): void {
59
+ this.hooks[hookType] = handler;
60
+ }
61
+
62
+ /**
63
+ * Execute a hook if it exists
64
+ */
65
+ public executeHook<K extends keyof MediaPluginHooks>(
66
+ hookType: K,
67
+ ...args: Parameters<NonNullable<MediaPluginHooks[K]>>
68
+ ): ReturnType<NonNullable<MediaPluginHooks[K]>> | void {
69
+ const hook = this.hooks[hookType];
70
+ if (hook) {
71
+ return (hook as any)(...args);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Get plugin priority
77
+ */
78
+ public getPriority(): number {
79
+ return this.priority;
80
+ }
81
+
82
+ /**
83
+ * Set middleware for advanced plugin behavior
84
+ */
85
+ public setMiddleware(middleware: PluginMiddleware): void {
86
+ this.middleware = middleware;
87
+ }
88
+ }
89
+
90
+ // Middleware interface for plugin system
91
+ export interface PluginMiddleware {
92
+ name: string;
93
+ priority: number;
94
+ execute: (
95
+ context: PluginContext,
96
+ next: () => PluginContext | Promise<PluginContext>
97
+ ) => PluginContext | Promise<PluginContext>;
98
+ }
99
+
100
+ // Plugin execution context
101
+ export interface PluginContext {
102
+ player: MediaPlayerInstance;
103
+ event: string;
104
+ data: any;
105
+ originalData: any;
106
+ modified: boolean;
107
+ stopped: boolean;
108
+ }
109
+
110
+ /**
111
+ * Enhanced Plugin Registry with hooks and middleware support
112
+ */
113
+ export class EnhancedPluginRegistry {
114
+ private plugins: Map<string, EnhancedMediaPlugin> = new Map();
115
+ private middlewares: PluginMiddleware[] = [];
116
+ private hooks: Map<keyof MediaPluginHooks, Array<{ plugin: string; handler: Function }>> = new Map();
117
+
118
+ /**
119
+ * Register a plugin with the system
120
+ */
121
+ public register(plugin: EnhancedMediaPlugin): void {
122
+ this.plugins.set(plugin.getName(), plugin);
123
+
124
+ // Register plugin hooks
125
+ this.registerPluginHooks(plugin);
126
+
127
+ // Register plugin middleware if available
128
+ if (plugin.middleware) {
129
+ this.addMiddleware(plugin.middleware);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Unregister a plugin
135
+ */
136
+ public unregister(pluginName: string): void {
137
+ const plugin = this.plugins.get(pluginName);
138
+ if (plugin) {
139
+ this.unregisterPluginHooks(plugin);
140
+ this.plugins.delete(pluginName);
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Get a registered plugin
146
+ */
147
+ public getPlugin(name: string): EnhancedMediaPlugin | undefined {
148
+ return this.plugins.get(name);
149
+ }
150
+
151
+ /**
152
+ * Get all registered plugins
153
+ */
154
+ public getPlugins(): EnhancedMediaPlugin[] {
155
+ return Array.from(this.plugins.values());
156
+ }
157
+
158
+ /**
159
+ * Get plugins sorted by priority
160
+ */
161
+ public getPluginsByPriority(): EnhancedMediaPlugin[] {
162
+ return Array.from(this.plugins.values()).sort((a, b) => a.getPriority() - b.getPriority());
163
+ }
164
+
165
+ /**
166
+ * Execute a hook across all registered plugins
167
+ */
168
+ public async executeHook<K extends keyof MediaPluginHooks>(
169
+ hookType: K,
170
+ ...args: Parameters<NonNullable<MediaPluginHooks[K]>>
171
+ ): Promise<any[]> {
172
+ const hookHandlers = this.hooks.get(hookType) || [];
173
+ const results: any[] = [];
174
+
175
+ for (const { plugin, handler } of hookHandlers) {
176
+ try {
177
+ const result = await (handler as any)(...args);
178
+ results.push({ plugin, result });
179
+ } catch (error) {
180
+ console.error(`Error executing hook ${hookType} in plugin ${plugin}:`, error);
181
+ }
182
+ }
183
+
184
+ return results;
185
+ }
186
+
187
+ /**
188
+ * Add middleware to the execution chain
189
+ */
190
+ public addMiddleware(middleware: PluginMiddleware): void {
191
+ this.middlewares.push(middleware);
192
+ // Sort by priority
193
+ this.middlewares.sort((a, b) => a.priority - b.priority);
194
+ }
195
+
196
+ /**
197
+ * Remove middleware
198
+ */
199
+ public removeMiddleware(name: string): void {
200
+ this.middlewares = this.middlewares.filter(m => m.name !== name);
201
+ }
202
+
203
+ /**
204
+ * Execute middleware chain
205
+ */
206
+ public async executeMiddleware(context: PluginContext): Promise<PluginContext> {
207
+ let index = 0;
208
+
209
+ const next = (): Promise<PluginContext> => {
210
+ if (index >= this.middlewares.length || context.stopped) {
211
+ return Promise.resolve(context);
212
+ }
213
+
214
+ const middleware = this.middlewares[index++];
215
+ return Promise.resolve(middleware.execute(context, next));
216
+ };
217
+
218
+ return next();
219
+ }
220
+
221
+ /**
222
+ * Register hooks from a plugin
223
+ */
224
+ private registerPluginHooks(plugin: EnhancedMediaPlugin): void {
225
+ const hooks = (plugin as any).hooks || {};
226
+
227
+ Object.entries(hooks).forEach(([hookType, handler]) => {
228
+ if (handler) {
229
+ if (!this.hooks.has(hookType as keyof MediaPluginHooks)) {
230
+ this.hooks.set(hookType as keyof MediaPluginHooks, []);
231
+ }
232
+
233
+ this.hooks.get(hookType as keyof MediaPluginHooks)!.push({
234
+ plugin: plugin.getName(),
235
+ handler,
236
+ });
237
+ }
238
+ });
239
+ }
240
+
241
+ /**
242
+ * Unregister hooks from a plugin
243
+ */
244
+ private unregisterPluginHooks(plugin: EnhancedMediaPlugin): void {
245
+ const hooks = (plugin as any).hooks || {};
246
+
247
+ Object.keys(hooks).forEach((hookType) => {
248
+ const handlers = this.hooks.get(hookType as keyof MediaPluginHooks);
249
+ if (handlers) {
250
+ this.hooks.set(
251
+ hookType as keyof MediaPluginHooks,
252
+ handlers.filter(h => h.plugin !== plugin.getName())
253
+ );
254
+ }
255
+ });
256
+ }
257
+
258
+ /**
259
+ * Clear all plugins and middleware
260
+ */
261
+ public clear(): void {
262
+ this.plugins.clear();
263
+ this.middlewares = [];
264
+ this.hooks.clear();
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Plugin Manager for enhanced plugin system integration
270
+ */
271
+ export class EnhancedPluginManager {
272
+ private registry: EnhancedPluginRegistry;
273
+ private player: MediaPlayerInstance;
274
+
275
+ constructor(player: MediaPlayerInstance) {
276
+ this.player = player;
277
+ this.registry = new EnhancedPluginRegistry();
278
+ }
279
+
280
+ /**
281
+ * Setup plugin system for player
282
+ */
283
+ public async setup(options: MediaPlayerConfig = {}): Promise<void> {
284
+ // Execute beforeSetup hooks
285
+ const setupResults = await this.registry.executeHook('beforeSetup', this.player.getElement(), options);
286
+
287
+ // Apply configuration modifications from hooks
288
+ const modifiedOptions = setupResults.reduce((acc, { result }) => {
289
+ return result || acc;
290
+ }, options);
291
+
292
+ // Execute setup hooks
293
+ await this.registry.executeHook('setup', this.player);
294
+
295
+ // Execute ready hooks
296
+ await this.registry.executeHook('ready', this.player);
297
+ }
298
+
299
+ /**
300
+ * Register a plugin
301
+ */
302
+ public register(plugin: EnhancedMediaPlugin): void {
303
+ this.registry.register(plugin);
304
+ }
305
+
306
+ /**
307
+ * Unregister a plugin
308
+ */
309
+ public unregister(pluginName: string): void {
310
+ this.registry.unregister(pluginName);
311
+ }
312
+
313
+ /**
314
+ * Execute hooks for specific events
315
+ */
316
+ public async handleEvent(event: string, data: any): Promise<void> {
317
+ const context: PluginContext = {
318
+ player: this.player,
319
+ event,
320
+ data,
321
+ originalData: data,
322
+ modified: false,
323
+ stopped: false,
324
+ };
325
+
326
+ // Execute middleware chain
327
+ const processedContext = await this.registry.executeMiddleware(context);
328
+
329
+ // Execute relevant hooks based on event
330
+ switch (event) {
331
+ case 'sourceLoaded':
332
+ await this.registry.executeHook('sourceLoaded', this.player, data.source);
333
+ break;
334
+ case 'playbackChange':
335
+ await this.registry.executeHook('playbackChange', this.player, data.isPlaying);
336
+ break;
337
+ case 'error':
338
+ await this.registry.executeHook('error', this.player, data.error);
339
+ break;
340
+ case 'qualityChange':
341
+ await this.registry.executeHook('qualityChange', this.player, data.quality);
342
+ break;
343
+ case 'volumeChange':
344
+ await this.registry.executeHook('volumeChange', this.player, data.volume);
345
+ break;
346
+ case 'fullscreenChange':
347
+ await this.registry.executeHook('fullscreenChange', this.player, data.isFullscreen);
348
+ break;
349
+ }
350
+ }
351
+
352
+ /**
353
+ * Dispose plugin manager
354
+ */
355
+ public async dispose(): Promise<void> {
356
+ // Execute beforeDispose hooks
357
+ await this.registry.executeHook('beforeDispose', this.player);
358
+
359
+ // Clear registry
360
+ this.registry.clear();
361
+ }
362
+
363
+ /**
364
+ * Get plugin registry
365
+ */
366
+ public getRegistry(): EnhancedPluginRegistry {
367
+ return this.registry;
368
+ }
369
+ }
370
+
371
+ // Default middlewares
372
+ export const createPerformanceMiddleware = (): PluginMiddleware => ({
373
+ name: 'performance',
374
+ priority: 0,
375
+ execute: async (context, next) => {
376
+ const start = performance.now();
377
+ const result = await next();
378
+ const duration = performance.now() - start;
379
+
380
+ if (duration > 16) { // Log slow operations
381
+ console.warn(`Slow plugin operation: ${context.event} took ${duration.toFixed(2)}ms`);
382
+ }
383
+
384
+ return result;
385
+ },
386
+ });
387
+
388
+ export const createErrorHandlingMiddleware = (): PluginMiddleware => ({
389
+ name: 'errorHandling',
390
+ priority: -1000, // Run last
391
+ execute: async (context, next) => {
392
+ try {
393
+ return await next();
394
+ } catch (error) {
395
+ console.error(`Plugin error in ${context.event}:`, error);
396
+ context.stopped = true;
397
+ return context;
398
+ }
399
+ },
400
+ });
401
+
402
+ export const createLoggingMiddleware = (): PluginMiddleware => ({
403
+ name: 'logging',
404
+ priority: 1000, // Run first
405
+ execute: async (context, next) => {
406
+ console.debug(`Plugin event: ${context.event}`, context.data);
407
+ return next();
408
+ },
409
+ });
410
+
411
+ export default EnhancedPluginManager;
@@ -0,0 +1,242 @@
1
+ import { BasePlugin, type AnalyticsPluginConfig } from '../base-plugin'
2
+
3
+ interface AnalyticsEvent {
4
+ event: string
5
+ timestamp: number
6
+ data?: any
7
+ }
8
+
9
+ interface AnalyticsConfig extends AnalyticsPluginConfig {
10
+ trackingId: string
11
+ events: string[]
12
+ samplingRate: number
13
+ debug: boolean
14
+ endpoint?: string
15
+ }
16
+
17
+ export class AnalyticsPlugin extends BasePlugin {
18
+ private events: AnalyticsEvent[] = []
19
+ private analyticsConfig!: AnalyticsConfig
20
+ private cleanupFunctions: Array<() => void> = []
21
+ private reportTimer?: NodeJS.Timeout
22
+
23
+ constructor(config?: AnalyticsPluginConfig) {
24
+ super({
25
+ name: 'analytics',
26
+ description: 'Media player analytics and tracking',
27
+ category: 'analytics',
28
+ priority: 'low',
29
+ author: 'BaroiPlayer Team'
30
+ })
31
+ }
32
+
33
+ protected onInitialize(): void {
34
+ this.analyticsConfig = this.createConfig<AnalyticsConfig>({
35
+ trackingId: '',
36
+ events: ['play', 'pause', 'seek', 'ended', 'error'],
37
+ samplingRate: 1.0,
38
+ debug: false,
39
+ endpoint: '/api/analytics'
40
+ })
41
+
42
+ if (!this.analyticsConfig.trackingId) {
43
+ throw new Error('Analytics plugin requires a tracking ID')
44
+ }
45
+
46
+ this.logger?.info('Analytics plugin initialized', {
47
+ trackingId: this.analyticsConfig.trackingId,
48
+ events: this.analyticsConfig.events
49
+ })
50
+ }
51
+
52
+ protected onActivate(): void {
53
+ // Set up event listeners for media events
54
+ const mediaEventCleanup = this.setupMediaEventListeners()
55
+ this.cleanupFunctions.push(mediaEventCleanup)
56
+
57
+ // Set up periodic reporting
58
+ if (this.analyticsConfig.endpoint) {
59
+ this.reportTimer = setInterval(() => {
60
+ this.reportEvents()
61
+ }, 30000) // Report every 30 seconds
62
+
63
+ this.cleanupFunctions.push(() => {
64
+ if (this.reportTimer) {
65
+ clearInterval(this.reportTimer)
66
+ }
67
+ })
68
+ }
69
+
70
+ this.trackEvent('plugin_activated', { plugin: 'analytics' })
71
+ this.logger?.info('Analytics tracking started')
72
+ }
73
+
74
+ protected onDeactivate(): void {
75
+ // Clean up all event listeners and timers
76
+ this.cleanupFunctions.forEach(cleanup => cleanup())
77
+ this.cleanupFunctions = []
78
+
79
+ // Report any remaining events
80
+ if (this.events.length > 0) {
81
+ this.reportEvents()
82
+ }
83
+
84
+ this.trackEvent('plugin_deactivated', { plugin: 'analytics' })
85
+ this.logger?.info('Analytics tracking stopped')
86
+ }
87
+
88
+ protected onConfigure(newConfig: AnalyticsConfig): void {
89
+ // Update tracking configuration
90
+ this.analyticsConfig = { ...this.analyticsConfig, ...newConfig }
91
+ if (newConfig.events) {
92
+ // Re-setup event listeners if events changed
93
+ this.cleanupFunctions.forEach(cleanup => cleanup())
94
+ this.cleanupFunctions = []
95
+
96
+ const mediaEventCleanup = this.setupMediaEventListeners()
97
+ this.cleanupFunctions.push(mediaEventCleanup)
98
+ }
99
+ }
100
+
101
+ private setupMediaEventListeners(): () => void {
102
+ const cleanupFunctions: Array<() => void> = []
103
+
104
+ // Listen for media state changes
105
+ if (this.analyticsConfig.events.includes('play')) {
106
+ const unsubscribe = this.on('media:play', (data) => {
107
+ this.trackEvent('play', data)
108
+ })
109
+ cleanupFunctions.push(unsubscribe)
110
+ }
111
+
112
+ if (this.analyticsConfig.events.includes('pause')) {
113
+ const unsubscribe = this.on('media:pause', (data) => {
114
+ this.trackEvent('pause', data)
115
+ })
116
+ cleanupFunctions.push(unsubscribe)
117
+ }
118
+
119
+ if (this.analyticsConfig.events.includes('seek')) {
120
+ const unsubscribe = this.on('media:seek', (data) => {
121
+ this.trackEvent('seek', data)
122
+ })
123
+ cleanupFunctions.push(unsubscribe)
124
+ }
125
+
126
+ if (this.analyticsConfig.events.includes('ended')) {
127
+ const unsubscribe = this.on('media:ended', (data) => {
128
+ this.trackEvent('ended', data)
129
+ })
130
+ cleanupFunctions.push(unsubscribe)
131
+ }
132
+
133
+ if (this.analyticsConfig.events.includes('error')) {
134
+ const unsubscribe = this.on('media:error', (data) => {
135
+ this.trackEvent('error', data)
136
+ })
137
+ cleanupFunctions.push(unsubscribe)
138
+ }
139
+
140
+ // Return cleanup function
141
+ return () => {
142
+ cleanupFunctions.forEach(cleanup => cleanup())
143
+ }
144
+ }
145
+
146
+ private trackEvent(event: string, data?: any): void {
147
+ // Apply sampling rate
148
+ if (Math.random() > this.analyticsConfig.samplingRate) {
149
+ return
150
+ }
151
+
152
+ const analyticsEvent: AnalyticsEvent = {
153
+ event,
154
+ timestamp: Date.now(),
155
+ data: {
156
+ ...data,
157
+ trackingId: this.analyticsConfig.trackingId,
158
+ sessionId: this.generateSessionId(),
159
+ mediaState: {
160
+ currentTime: this.state?.currentTime,
161
+ duration: this.state?.duration,
162
+ volume: this.state?.volume,
163
+ isPlaying: this.state?.isPlaying
164
+ }
165
+ }
166
+ }
167
+
168
+ this.events.push(analyticsEvent)
169
+
170
+ if (this.analyticsConfig.debug) {
171
+ this.logger?.info('Analytics event tracked', analyticsEvent)
172
+ }
173
+
174
+ // Emit event for other plugins or applications to use
175
+ this.emit('analytics:event', analyticsEvent)
176
+ }
177
+
178
+ private async reportEvents(): Promise<void> {
179
+ if (this.events.length === 0 || !this.analyticsConfig.endpoint) {
180
+ return
181
+ }
182
+
183
+ const eventsToReport = [...this.events]
184
+ this.events = []
185
+
186
+ try {
187
+ const response = await fetch(this.analyticsConfig.endpoint, {
188
+ method: 'POST',
189
+ headers: {
190
+ 'Content-Type': 'application/json'
191
+ },
192
+ body: JSON.stringify({
193
+ trackingId: this.analyticsConfig.trackingId,
194
+ events: eventsToReport
195
+ })
196
+ })
197
+
198
+ if (!response.ok) {
199
+ throw new Error(`Analytics report failed: ${response.status}`)
200
+ }
201
+
202
+ if (this.analyticsConfig.debug) {
203
+ this.logger?.info(`Reported ${eventsToReport.length} analytics events`)
204
+ }
205
+
206
+ } catch (error) {
207
+ // Put events back in queue on failure
208
+ this.events.unshift(...eventsToReport)
209
+ this.logger?.error('Failed to report analytics events', error)
210
+ }
211
+ }
212
+
213
+ private generateSessionId(): string {
214
+ // Simple session ID generation - could be more sophisticated
215
+ return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
216
+ }
217
+
218
+ // Public API for manual event tracking
219
+ public track(event: string, data?: any): void {
220
+ this.trackEvent(event, data)
221
+ }
222
+
223
+ // Get pending events count
224
+ public getPendingEventsCount(): number {
225
+ return this.events.length
226
+ }
227
+
228
+ // Flush all pending events
229
+ public async flush(): Promise<void> {
230
+ await this.reportEvents()
231
+ }
232
+
233
+ protected onHealthCheck(): boolean {
234
+ // Check if we're not accumulating too many events
235
+ return this.events.length < 1000
236
+ }
237
+ }
238
+
239
+ // Plugin factory
240
+ export const createAnalyticsPlugin = (config?: AnalyticsPluginConfig) => {
241
+ return new AnalyticsPlugin(config)
242
+ }
@@ -0,0 +1,39 @@
1
+ // Plugin system core exports
2
+ export type {
3
+ Plugin,
4
+ PluginFactory,
5
+ PluginConfig,
6
+ PluginRegistry as IPluginRegistry,
7
+ PluginContext,
8
+ PluginLogger,
9
+ PluginMetadata,
10
+ PluginCategory,
11
+ PluginPriority,
12
+ PluginPhase,
13
+ PluginEvents
14
+ } from './types'
15
+
16
+ export {
17
+ PluginError,
18
+ PluginDependencyError,
19
+ PluginConflictError
20
+ } from './types'
21
+
22
+ export { PluginRegistry } from './registry'
23
+
24
+ export {
25
+ BasePlugin,
26
+ createPlugin,
27
+ type UIPluginConfig,
28
+ type AnalyticsPluginConfig,
29
+ type PerformancePluginConfig
30
+ } from './base-plugin'
31
+
32
+ // Example plugins
33
+ export { AnalyticsPlugin, createAnalyticsPlugin } from './examples/analytics-plugin'
34
+
35
+ // Plugin utilities
36
+ export * from './utils'
37
+
38
+ // Version
39
+ export const PLUGIN_SYSTEM_VERSION = '1.0.0'