@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,327 @@
1
+ import { EventBus } from '../events/event-system'
2
+ import type {
3
+ Plugin,
4
+ PluginFactory,
5
+ PluginConfig,
6
+ PluginRegistry as IPluginRegistry,
7
+ PluginContext,
8
+ PluginLogger,
9
+ PluginEvents,
10
+ PluginPriority
11
+ } from './types'
12
+ import {
13
+ PluginError,
14
+ PluginDependencyError,
15
+ PluginConflictError
16
+ } from './types'
17
+
18
+ // Plugin registry implementation
19
+ export class PluginRegistry implements IPluginRegistry {
20
+ private plugins = new Map<string, Plugin>()
21
+ private pluginConfigs = new Map<string, PluginConfig>()
22
+ private enabledPlugins = new Set<string>()
23
+ private eventBus = new EventBus()
24
+ private logger: PluginLogger
25
+
26
+ constructor(logger: PluginLogger) {
27
+ this.logger = logger
28
+ }
29
+
30
+ // Register a plugin factory
31
+ async register(factory: PluginFactory, config: PluginConfig = {}): Promise<void> {
32
+ try {
33
+ const plugin = factory(config)
34
+ const { name, dependencies = [], conflicts = [] } = plugin.metadata
35
+
36
+ // Check if plugin already exists
37
+ if (this.plugins.has(name)) {
38
+ throw new PluginError(name, 'initialize', 'Plugin already registered')
39
+ }
40
+
41
+ // Validate dependencies
42
+ const missingDependencies = dependencies.filter(dep => !this.plugins.has(dep))
43
+ if (missingDependencies.length > 0) {
44
+ throw new PluginDependencyError(name, missingDependencies)
45
+ }
46
+
47
+ // Check for conflicts with enabled plugins
48
+ const activeConflicts = conflicts.filter(conflict => this.enabledPlugins.has(conflict))
49
+ if (activeConflicts.length > 0) {
50
+ throw new PluginConflictError(name, activeConflicts)
51
+ }
52
+
53
+ // Store plugin and configuration
54
+ this.plugins.set(name, plugin)
55
+ this.pluginConfigs.set(name, config)
56
+
57
+ this.logger.info(`Plugin '${name}' registered successfully`)
58
+ ;(this.eventBus as any).emit('plugin:registered', { name, plugin })
59
+
60
+ } catch (error) {
61
+ const pluginName = factory({}).metadata.name
62
+ this.logger.error(`Failed to register plugin '${pluginName}'`, error)
63
+ ;(this.eventBus as any).emit('plugin:error', { name: pluginName, error: error as Error })
64
+ throw error
65
+ }
66
+ }
67
+
68
+ // Unregister a plugin
69
+ async unregister(name: string): Promise<void> {
70
+ const plugin = this.plugins.get(name)
71
+ if (!plugin) {
72
+ throw new PluginError(name, 'destroy', 'Plugin not found')
73
+ }
74
+
75
+ try {
76
+ // Disable plugin if enabled
77
+ if (this.enabledPlugins.has(name)) {
78
+ await this.disable(name)
79
+ }
80
+
81
+ // Remove from registry
82
+ this.plugins.delete(name)
83
+ this.pluginConfigs.delete(name)
84
+
85
+ this.logger.info(`Plugin '${name}' unregistered successfully`)
86
+ } catch (error) {
87
+ this.logger.error(`Failed to unregister plugin '${name}'`, error)
88
+ throw error
89
+ }
90
+ }
91
+
92
+ // Get a plugin by name
93
+ get(name: string): Plugin | undefined {
94
+ return this.plugins.get(name)
95
+ }
96
+
97
+ // Get all plugins sorted by priority
98
+ getAll(): Plugin[] {
99
+ return Array.from(this.plugins.values()).sort(this.sortByPriority)
100
+ }
101
+
102
+ // Check if plugin is enabled
103
+ isEnabled(name: string): boolean {
104
+ return this.enabledPlugins.has(name)
105
+ }
106
+
107
+ // Enable a plugin
108
+ async enable(name: string): Promise<void> {
109
+ const plugin = this.plugins.get(name)
110
+ if (!plugin) {
111
+ throw new PluginError(name, 'activate', 'Plugin not found')
112
+ }
113
+
114
+ if (this.enabledPlugins.has(name)) {
115
+ this.logger.warn(`Plugin '${name}' is already enabled`)
116
+ return
117
+ }
118
+
119
+ try {
120
+ const context = this.createPluginContext(name)
121
+ const config = this.pluginConfigs.get(name)
122
+
123
+ // Initialize plugin
124
+ await plugin.initialize(context, config)
125
+
126
+ // Activate plugin
127
+ await plugin.activate(context)
128
+
129
+ this.enabledPlugins.add(name)
130
+ this.logger.info(`Plugin '${name}' enabled successfully`)
131
+ ;(this.eventBus as any).emit('plugin:enabled', { name, plugin })
132
+
133
+ } catch (error) {
134
+ this.logger.error(`Failed to enable plugin '${name}'`, error)
135
+ ;(this.eventBus as any).emit('plugin:error', { name, error: error as Error })
136
+ throw error
137
+ }
138
+ }
139
+
140
+ // Disable a plugin
141
+ async disable(name: string): Promise<void> {
142
+ const plugin = this.plugins.get(name)
143
+ if (!plugin) {
144
+ throw new PluginError(name, 'deactivate', 'Plugin not found')
145
+ }
146
+
147
+ if (!this.enabledPlugins.has(name)) {
148
+ this.logger.warn(`Plugin '${name}' is already disabled`)
149
+ return
150
+ }
151
+
152
+ try {
153
+ const context = this.createPluginContext(name)
154
+
155
+ // Deactivate plugin
156
+ await plugin.deactivate(context)
157
+
158
+ // Destroy plugin resources
159
+ await plugin.destroy(context)
160
+
161
+ this.enabledPlugins.delete(name)
162
+ this.logger.info(`Plugin '${name}' disabled successfully`)
163
+ ;(this.eventBus as any).emit('plugin:disabled', { name, plugin })
164
+
165
+ } catch (error) {
166
+ this.logger.error(`Failed to disable plugin '${name}'`, error)
167
+ ;(this.eventBus as any).emit('plugin:error', { name, error: error as Error })
168
+ throw error
169
+ }
170
+ }
171
+
172
+ // Configure a plugin
173
+ async configure(name: string, config: PluginConfig): Promise<void> {
174
+ const plugin = this.plugins.get(name)
175
+ if (!plugin) {
176
+ throw new PluginError(name, 'initialize', 'Plugin not found')
177
+ }
178
+
179
+ try {
180
+ // Update stored configuration
181
+ this.pluginConfigs.set(name, { ...this.pluginConfigs.get(name), ...config })
182
+
183
+ // If plugin has configure method, call it
184
+ if (plugin.configure) {
185
+ await plugin.configure(config)
186
+ }
187
+
188
+ this.logger.info(`Plugin '${name}' configured successfully`)
189
+ ;(this.eventBus as any).emit('plugin:configured', { name, config })
190
+
191
+ } catch (error) {
192
+ this.logger.error(`Failed to configure plugin '${name}'`, error)
193
+ ;(this.eventBus as any).emit('plugin:error', { name, error: error as Error })
194
+ throw error
195
+ }
196
+ }
197
+
198
+ // Enable multiple plugins with dependency resolution
199
+ async enablePlugins(names: string[]): Promise<void> {
200
+ const resolved = this.resolveDependencies(names)
201
+
202
+ for (const name of resolved) {
203
+ if (!this.enabledPlugins.has(name)) {
204
+ await this.enable(name)
205
+ }
206
+ }
207
+ }
208
+
209
+ // Disable multiple plugins
210
+ async disablePlugins(names: string[]): Promise<void> {
211
+ // Disable in reverse order to handle dependencies
212
+ const reversed = [...names].reverse()
213
+
214
+ for (const name of reversed) {
215
+ if (this.enabledPlugins.has(name)) {
216
+ await this.disable(name)
217
+ }
218
+ }
219
+ }
220
+
221
+ // Get enabled plugins
222
+ getEnabledPlugins(): Plugin[] {
223
+ return Array.from(this.enabledPlugins)
224
+ .map(name => this.plugins.get(name)!)
225
+ .filter(Boolean)
226
+ .sort(this.sortByPriority)
227
+ }
228
+
229
+ // Health check for all enabled plugins
230
+ async healthCheck(): Promise<{ name: string; healthy: boolean; error?: Error }[]> {
231
+ const results = []
232
+
233
+ for (const name of this.enabledPlugins) {
234
+ const plugin = this.plugins.get(name)!
235
+ try {
236
+ const healthy = plugin.healthCheck ? await plugin.healthCheck() : true
237
+ results.push({ name, healthy })
238
+ } catch (error) {
239
+ results.push({ name, healthy: false, error: error as Error })
240
+ }
241
+ }
242
+
243
+ return results
244
+ }
245
+
246
+ // Event handling
247
+ on<K extends keyof PluginEvents>(
248
+ event: K,
249
+ listener: (data: PluginEvents[K]) => void
250
+ ): () => void {
251
+ (this.eventBus as any).on(event, listener)
252
+ return () => (this.eventBus as any).off(event, listener)
253
+ }
254
+
255
+ // Create plugin context (will be implemented when we have the full context)
256
+ private createPluginContext(pluginName: string): PluginContext {
257
+ // This will be implemented when we integrate with the media player
258
+ // For now, return a minimal context
259
+ return {
260
+ state: {} as any,
261
+ controls: {} as any,
262
+ plugins: this,
263
+ emit: (event: string, data?: any) => (this.eventBus as any).emit(event, data),
264
+ on: (event: string, handler: (data: any) => void) => {
265
+ (this.eventBus as any).on(event, handler)
266
+ return () => (this.eventBus as any).off(event, handler)
267
+ },
268
+ element: null,
269
+ logger: this.createPluginLogger(pluginName)
270
+ }
271
+ }
272
+
273
+ // Create plugin-specific logger
274
+ private createPluginLogger(pluginName: string): PluginLogger {
275
+ return {
276
+ info: (message: string, data?: any) => this.logger.info(`[${pluginName}] ${message}`, data),
277
+ warn: (message: string, data?: any) => this.logger.warn(`[${pluginName}] ${message}`, data),
278
+ error: (message: string, data?: any) => this.logger.error(`[${pluginName}] ${message}`, data),
279
+ debug: (message: string, data?: any) => this.logger.debug(`[${pluginName}] ${message}`, data)
280
+ }
281
+ }
282
+
283
+ // Resolve plugin dependencies
284
+ private resolveDependencies(names: string[]): string[] {
285
+ const resolved: string[] = []
286
+ const visiting = new Set<string>()
287
+
288
+ const visit = (name: string) => {
289
+ if (resolved.includes(name)) return
290
+ if (visiting.has(name)) {
291
+ throw new PluginError(name, 'initialize', 'Circular dependency detected')
292
+ }
293
+
294
+ visiting.add(name)
295
+
296
+ const plugin = this.plugins.get(name)
297
+ if (!plugin) {
298
+ throw new PluginError(name, 'initialize', 'Plugin not found')
299
+ }
300
+
301
+ // Visit dependencies first
302
+ for (const dep of plugin.metadata.dependencies || []) {
303
+ visit(dep)
304
+ }
305
+
306
+ visiting.delete(name)
307
+ resolved.push(name)
308
+ }
309
+
310
+ for (const name of names) {
311
+ visit(name)
312
+ }
313
+
314
+ return resolved
315
+ }
316
+
317
+ // Sort plugins by priority
318
+ private sortByPriority(a: Plugin, b: Plugin): number {
319
+ const priorityOrder: Record<PluginPriority, number> = {
320
+ high: 3,
321
+ medium: 2,
322
+ low: 1
323
+ }
324
+
325
+ return priorityOrder[b.metadata.priority] - priorityOrder[a.metadata.priority]
326
+ }
327
+ }
@@ -0,0 +1,159 @@
1
+ // TODO: Import proper types when integrated
2
+ export interface MediaState {
3
+ isPlaying: boolean
4
+ currentTime: number
5
+ duration: number
6
+ volume: number
7
+ isMuted: boolean
8
+ }
9
+
10
+ export interface MediaPlayerControls {
11
+ play(): void
12
+ pause(): void
13
+ seek(time: number): void
14
+ setVolume(volume: number): void
15
+ }
16
+
17
+ // Plugin lifecycle phases
18
+ export type PluginPhase = 'initialize' | 'activate' | 'deactivate' | 'destroy'
19
+
20
+ // Plugin categories for organization
21
+ export type PluginCategory =
22
+ | 'controls'
23
+ | 'analytics'
24
+ | 'streaming'
25
+ | 'subtitle'
26
+ | 'quality'
27
+ | 'ui'
28
+ | 'accessibility'
29
+ | 'performance'
30
+
31
+ // Plugin priority for execution order
32
+ export type PluginPriority = 'high' | 'medium' | 'low'
33
+
34
+ // Plugin configuration interface
35
+ export interface PluginConfig {
36
+ [key: string]: any
37
+ }
38
+
39
+ // Plugin context provided to each plugin
40
+ export interface PluginContext {
41
+ // Core media player state and controls
42
+ state: MediaState
43
+ controls: MediaPlayerControls
44
+
45
+ // Plugin management
46
+ plugins: PluginRegistry
47
+
48
+ // Event system
49
+ emit: (event: string, data?: any) => void
50
+ on: (event: string, handler: (data: any) => void) => () => void
51
+
52
+ // Utilities
53
+ element: HTMLElement | null
54
+ logger: PluginLogger
55
+ }
56
+
57
+ // Plugin metadata
58
+ export interface PluginMetadata {
59
+ name: string
60
+ version: string
61
+ description: string
62
+ author?: string
63
+ category: PluginCategory
64
+ priority: PluginPriority
65
+ dependencies?: string[]
66
+ conflicts?: string[]
67
+ }
68
+
69
+ // Plugin interface that all plugins must implement
70
+ export interface Plugin {
71
+ metadata: PluginMetadata
72
+
73
+ // Plugin lifecycle methods
74
+ initialize(context: PluginContext, config?: PluginConfig): Promise<void> | void
75
+ activate(context: PluginContext): Promise<void> | void
76
+ deactivate(context: PluginContext): Promise<void> | void
77
+ destroy(context: PluginContext): Promise<void> | void
78
+
79
+ // Configuration handling
80
+ configure?(config: PluginConfig): Promise<void> | void
81
+
82
+ // Health check for plugin status
83
+ healthCheck?(): Promise<boolean> | boolean
84
+ }
85
+
86
+ // Plugin factory function type
87
+ export type PluginFactory<T extends Plugin = Plugin> = (config?: PluginConfig) => T
88
+
89
+ // Plugin registry interface
90
+ export interface PluginRegistry {
91
+ register(factory: PluginFactory, config?: PluginConfig): Promise<void>
92
+ unregister(name: string): Promise<void>
93
+ get(name: string): Plugin | undefined
94
+ getAll(): Plugin[]
95
+ isEnabled(name: string): boolean
96
+ enable(name: string): Promise<void>
97
+ disable(name: string): Promise<void>
98
+ configure(name: string, config: PluginConfig): Promise<void>
99
+ }
100
+
101
+ // Plugin logger interface
102
+ export interface PluginLogger {
103
+ info(message: string, data?: any): void
104
+ warn(message: string, data?: any): void
105
+ error(message: string, data?: any): void
106
+ debug(message: string, data?: any): void
107
+ }
108
+
109
+ // Plugin event types
110
+ export interface PluginEvents {
111
+ 'plugin:registered': { name: string; plugin: Plugin }
112
+ 'plugin:enabled': { name: string; plugin: Plugin }
113
+ 'plugin:disabled': { name: string; plugin: Plugin }
114
+ 'plugin:error': { name: string; error: Error }
115
+ 'plugin:configured': { name: string; config: PluginConfig }
116
+ }
117
+
118
+ // Plugin error types
119
+ export class PluginError extends Error {
120
+ constructor(
121
+ public pluginName: string,
122
+ public phase: PluginPhase,
123
+ message: string,
124
+ public originalError?: Error
125
+ ) {
126
+ super(`Plugin '${pluginName}' failed during ${phase}: ${message}`)
127
+ this.name = 'PluginError'
128
+ }
129
+ }
130
+
131
+ // Plugin dependency error
132
+ export class PluginDependencyError extends PluginError {
133
+ constructor(
134
+ pluginName: string,
135
+ public missingDependencies: string[]
136
+ ) {
137
+ super(
138
+ pluginName,
139
+ 'initialize',
140
+ `Missing dependencies: ${missingDependencies.join(', ')}`
141
+ )
142
+ this.name = 'PluginDependencyError'
143
+ }
144
+ }
145
+
146
+ // Plugin conflict error
147
+ export class PluginConflictError extends PluginError {
148
+ constructor(
149
+ pluginName: string,
150
+ public conflictingPlugins: string[]
151
+ ) {
152
+ super(
153
+ pluginName,
154
+ 'activate',
155
+ `Conflicts with active plugins: ${conflictingPlugins.join(', ')}`
156
+ )
157
+ this.name = 'PluginConflictError'
158
+ }
159
+ }