@therealtinhtute/baroiplayer 1.2.1 → 2.0.0-beta.1

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 (302) hide show
  1. package/README.md +90 -71
  2. package/dist/components/icons/index.d.ts +36 -0
  3. package/dist/components/icons/index.d.ts.map +1 -0
  4. package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts +4 -0
  5. package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts.map +1 -0
  6. package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts +5 -0
  7. package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts.map +1 -0
  8. package/dist/components/icons/svg-icons/AudioIcon.d.ts +5 -0
  9. package/dist/components/icons/svg-icons/AudioIcon.d.ts.map +1 -0
  10. package/dist/components/icons/svg-icons/BackwardIcon.d.ts +5 -0
  11. package/dist/components/icons/svg-icons/BackwardIcon.d.ts.map +1 -0
  12. package/dist/components/icons/svg-icons/CameraIcon.d.ts +5 -0
  13. package/dist/components/icons/svg-icons/CameraIcon.d.ts.map +1 -0
  14. package/dist/components/icons/svg-icons/CheckIcon.d.ts +5 -0
  15. package/dist/components/icons/svg-icons/CheckIcon.d.ts.map +1 -0
  16. package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts +4 -0
  17. package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts.map +1 -0
  18. package/dist/components/icons/svg-icons/ForwardIcon.d.ts +5 -0
  19. package/dist/components/icons/svg-icons/ForwardIcon.d.ts.map +1 -0
  20. package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts +5 -0
  21. package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts.map +1 -0
  22. package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts +5 -0
  23. package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts.map +1 -0
  24. package/dist/components/icons/svg-icons/LoadingIcon.d.ts +5 -0
  25. package/dist/components/icons/svg-icons/LoadingIcon.d.ts.map +1 -0
  26. package/dist/components/icons/svg-icons/PauseIcon.d.ts +5 -0
  27. package/dist/components/icons/svg-icons/PauseIcon.d.ts.map +1 -0
  28. package/dist/components/icons/svg-icons/PlayIcon.d.ts +5 -0
  29. package/dist/components/icons/svg-icons/PlayIcon.d.ts.map +1 -0
  30. package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts +5 -0
  31. package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts.map +1 -0
  32. package/dist/components/icons/svg-icons/QualityIcon.d.ts +5 -0
  33. package/dist/components/icons/svg-icons/QualityIcon.d.ts.map +1 -0
  34. package/dist/components/icons/svg-icons/SettingsIcon.d.ts +5 -0
  35. package/dist/components/icons/svg-icons/SettingsIcon.d.ts.map +1 -0
  36. package/dist/components/icons/svg-icons/SliderIcon.d.ts +5 -0
  37. package/dist/components/icons/svg-icons/SliderIcon.d.ts.map +1 -0
  38. package/dist/components/icons/svg-icons/SubtitleIcon.d.ts +5 -0
  39. package/dist/components/icons/svg-icons/SubtitleIcon.d.ts.map +1 -0
  40. package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts +5 -0
  41. package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts.map +1 -0
  42. package/dist/components/icons/svg-icons/UnPiPIcon.d.ts +4 -0
  43. package/dist/components/icons/svg-icons/UnPiPIcon.d.ts.map +1 -0
  44. package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts +5 -0
  45. package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts.map +1 -0
  46. package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts +5 -0
  47. package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts.map +1 -0
  48. package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts +5 -0
  49. package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts.map +1 -0
  50. package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts +5 -0
  51. package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts.map +1 -0
  52. package/dist/components/variants/gradient/gradient-audio.d.ts +13 -0
  53. package/dist/components/variants/gradient/gradient-audio.d.ts.map +1 -0
  54. package/dist/components/variants/gradient/gradient-controls.d.ts +4 -0
  55. package/dist/components/variants/gradient/gradient-controls.d.ts.map +1 -0
  56. package/dist/components/variants/gradient/gradient-glyphs.d.ts +30 -0
  57. package/dist/components/variants/gradient/gradient-glyphs.d.ts.map +1 -0
  58. package/dist/components/variants/gradient/gradient-video.d.ts +16 -0
  59. package/dist/components/variants/gradient/gradient-video.d.ts.map +1 -0
  60. package/dist/index.css +1 -1
  61. package/dist/index.d.ts +5 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +1 -41
  64. package/dist/index.js.map +1 -1
  65. package/dist/index.mjs +750 -5640
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/package.json +3 -0
  68. package/package.json +110 -114
  69. package/src/components/variants/gradient/gradient-audio.tsx +47 -0
  70. package/src/components/variants/gradient/gradient-controls.tsx +254 -0
  71. package/src/components/variants/gradient/gradient-glyphs.test.tsx +69 -0
  72. package/src/components/variants/gradient/gradient-glyphs.tsx +129 -0
  73. package/src/components/variants/gradient/gradient-skin.css +211 -0
  74. package/src/components/variants/gradient/gradient-video.tsx +70 -0
  75. package/src/index.ts +5 -198
  76. package/src/test/accessibility-utils.ts +0 -59
  77. package/dist/context/media.js +0 -1
  78. package/dist/context/media.mjs +0 -3
  79. package/dist/context/store.js +0 -1
  80. package/dist/context/store.mjs +0 -3
  81. package/dist/context-Bzd5QCKM.cjs +0 -7
  82. package/dist/context-Bzd5QCKM.cjs.map +0 -1
  83. package/dist/context-DD_SH4tT.js +0 -1053
  84. package/dist/context-DD_SH4tT.js.map +0 -1
  85. package/dist/core-events-BRnLMB7s.cjs +0 -2
  86. package/dist/core-events-BRnLMB7s.cjs.map +0 -1
  87. package/dist/core-events-v_mKdj5p.js +0 -417
  88. package/dist/core-events-v_mKdj5p.js.map +0 -1
  89. package/dist/core-plugins-CMBv-yVh.cjs +0 -2
  90. package/dist/core-plugins-CMBv-yVh.cjs.map +0 -1
  91. package/dist/core-plugins-CqCxLkbd.js +0 -754
  92. package/dist/core-plugins-CqCxLkbd.js.map +0 -1
  93. package/dist/core.js +0 -15
  94. package/dist/core.js.map +0 -1
  95. package/dist/core.mjs +0 -960
  96. package/dist/core.mjs.map +0 -1
  97. package/dist/enhanced-components-BwjBqSA1.js +0 -2858
  98. package/dist/enhanced-components-BwjBqSA1.js.map +0 -1
  99. package/dist/enhanced-components-C-ka-XLp.cjs +0 -2
  100. package/dist/enhanced-components-C-ka-XLp.cjs.map +0 -1
  101. package/dist/hooks-B-IIWPJr.js +0 -1842
  102. package/dist/hooks-B-IIWPJr.js.map +0 -1
  103. package/dist/hooks-DcHzmBwA.cjs +0 -4
  104. package/dist/hooks-DcHzmBwA.cjs.map +0 -1
  105. package/dist/minimal-components-BYsMQde5.js +0 -1610
  106. package/dist/minimal-components-BYsMQde5.js.map +0 -1
  107. package/dist/minimal-components-CsxQbDp7.cjs +0 -2
  108. package/dist/minimal-components-CsxQbDp7.cjs.map +0 -1
  109. package/dist/minimal-components.css +0 -1
  110. package/dist/mona-loading.gif +0 -0
  111. package/dist/performance-monitor-DCSijLJg.js +0 -312
  112. package/dist/performance-monitor-DCSijLJg.js.map +0 -1
  113. package/dist/performance-monitor-wNFKmqMr.cjs +0 -2
  114. package/dist/performance-monitor-wNFKmqMr.cjs.map +0 -1
  115. package/dist/rolldown-runtime-BmowowmI.js +0 -14
  116. package/dist/rolldown-runtime-mLOUI7ql.cjs +0 -1
  117. package/dist/utils-D2gQ7c2R.js +0 -64
  118. package/dist/utils-D2gQ7c2R.js.map +0 -1
  119. package/dist/utils-DJaAwiZ9.cjs +0 -2
  120. package/dist/utils-DJaAwiZ9.cjs.map +0 -1
  121. package/dist/utils.js +0 -1
  122. package/dist/utils.mjs +0 -3
  123. package/src/adapters/videojs-adapter.tsx +0 -470
  124. package/src/assets/mona-loading.gif +0 -0
  125. package/src/components/AnimateLoading.tsx +0 -111
  126. package/src/components/LoadingState.tsx +0 -239
  127. package/src/components/__tests__/media-player-accessibility.test.tsx +0 -510
  128. package/src/components/__tests__/media-player-react19.test.tsx +0 -457
  129. package/src/components/accessibility/keyboard-help-overlay.tsx +0 -207
  130. package/src/components/audio-player.tsx +0 -85
  131. package/src/components/basic/index.ts +0 -37
  132. package/src/components/enhanced/advanced-features.tsx +0 -311
  133. package/src/components/enhanced/debug-panel.tsx +0 -448
  134. package/src/components/enhanced/enhanced-controls.tsx +0 -597
  135. package/src/components/enhanced/enhanced-media-player.tsx +0 -566
  136. package/src/components/enhanced/error-handling.tsx +0 -338
  137. package/src/components/enhanced/index.ts +0 -39
  138. package/src/components/enhanced/media-player-enhanced.tsx +0 -383
  139. package/src/components/examples/basic-video-player.tsx +0 -50
  140. package/src/components/examples/custom-controls-example.tsx +0 -63
  141. package/src/components/examples/enhanced-controls-example.tsx +0 -100
  142. package/src/components/examples/enhanced-media-player-example.tsx +0 -302
  143. package/src/components/examples/loading-states-demo.tsx +0 -141
  144. package/src/components/examples/react-19-demo.tsx +0 -349
  145. package/src/components/examples/volume-orientation-demo.tsx +0 -105
  146. package/src/components/icon-demo.tsx +0 -196
  147. package/src/components/legacy.tsx +0 -87
  148. package/src/components/media-metadata-display.tsx +0 -99
  149. package/src/components/media-player-audio.tsx +0 -39
  150. package/src/components/media-player-controls.tsx +0 -223
  151. package/src/components/media-player-error.tsx +0 -163
  152. package/src/components/media-player-fullscreen.tsx +0 -109
  153. package/src/components/media-player-hls.tsx +0 -111
  154. package/src/components/media-player-loading.tsx +0 -76
  155. package/src/components/media-player-play.tsx +0 -75
  156. package/src/components/media-player-root.tsx +0 -338
  157. package/src/components/media-player-seek.tsx +0 -168
  158. package/src/components/media-player-time.tsx +0 -99
  159. package/src/components/media-player-tooltip.tsx +0 -58
  160. package/src/components/media-player-video.tsx +0 -54
  161. package/src/components/media-player-volume.tsx +0 -155
  162. package/src/components/media-player.tsx +0 -292
  163. package/src/components/media-suspense.tsx +0 -344
  164. package/src/components/player-settings-form.tsx +0 -158
  165. package/src/components/react-player-wrapper.tsx +0 -651
  166. package/src/components/simple-video-player.tsx +0 -62
  167. package/src/components/ui/blur-poster.tsx +0 -96
  168. package/src/components/ui/empty-state.tsx +0 -91
  169. package/src/components/ui/enhanced-seek-bar.tsx +0 -254
  170. package/src/components/ui/error-state.tsx +0 -124
  171. package/src/components/ui/fullscreen-button.tsx +0 -81
  172. package/src/components/ui/loading-skeleton.tsx +0 -107
  173. package/src/components/ui/media-resource-preloader.tsx +0 -458
  174. package/src/components/ui/offline-message.tsx +0 -98
  175. package/src/components/ui/play-button.tsx +0 -99
  176. package/src/components/ui/seek-bar.tsx +0 -191
  177. package/src/components/ui/time-display.tsx +0 -61
  178. package/src/components/ui/volume-control.tsx +0 -190
  179. package/src/components/unified/base-media-player.tsx +0 -252
  180. package/src/components/unified/media-player.tsx +0 -75
  181. package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +0 -587
  182. package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +0 -573
  183. package/src/components/variants/minimal/MinimalControls.tsx +0 -124
  184. package/src/components/variants/minimal/MinimalLoading.tsx +0 -28
  185. package/src/components/variants/minimal/MinimalMediaPlayer.tsx +0 -318
  186. package/src/components/variants/minimal/MinimalOverlay.tsx +0 -58
  187. package/src/components/variants/minimal/MinimalPlayButton.tsx +0 -56
  188. package/src/components/variants/minimal/MinimalSeekBar.tsx +0 -140
  189. package/src/components/variants/minimal/MinimalVolumeControl.tsx +0 -75
  190. package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +0 -206
  191. package/src/components/variants/minimal/components/CenterPlayButton.tsx +0 -22
  192. package/src/components/variants/minimal/components/ControlBar.tsx +0 -142
  193. package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +0 -412
  194. package/src/components/variants/minimal/components/PlaybackControls.tsx +0 -46
  195. package/src/components/variants/minimal/components/RightControls.tsx +0 -164
  196. package/src/components/variants/minimal/components/SeekBar.tsx +0 -127
  197. package/src/components/variants/minimal/components/SettingsDropdown.tsx +0 -68
  198. package/src/components/variants/minimal/components/SubtitleDisplay.tsx +0 -21
  199. package/src/components/variants/minimal/components/TimeDisplay.tsx +0 -15
  200. package/src/components/variants/minimal/components/VideoElement.tsx +0 -35
  201. package/src/components/variants/minimal/components/VolumeControl.tsx +0 -220
  202. package/src/components/variants/minimal/index.ts +0 -23
  203. package/src/components/video-player.tsx +0 -100
  204. package/src/context/__tests__/media-store.test.ts +0 -509
  205. package/src/context/error-handling.ts +0 -398
  206. package/src/context/media-context.tsx +0 -254
  207. package/src/context/media-provider.tsx +0 -264
  208. package/src/context/media-store.ts +0 -387
  209. package/src/context/persistence.ts +0 -462
  210. package/src/core/events/event-system.ts +0 -448
  211. package/src/core/events/hooks.ts +0 -325
  212. package/src/core/events/index.ts +0 -22
  213. package/src/core/events/middleware.ts +0 -286
  214. package/src/core/index.ts +0 -22
  215. package/src/core/optimization/bundle-optimizer.tsx +0 -312
  216. package/src/core/performance/cicd.ts +0 -98
  217. package/src/core/performance/index.ts +0 -38
  218. package/src/core/performance/media-loading-optimizer.ts +0 -545
  219. package/src/core/performance/performance-budgets.ts +0 -437
  220. package/src/core/performance/performance-monitor.tsx +0 -488
  221. package/src/core/performance/performance-testing.ts +0 -461
  222. package/src/core/plugins/__tests__/registry.test.ts +0 -595
  223. package/src/core/plugins/base-plugin.ts +0 -225
  224. package/src/core/plugins/enhanced-plugin-system.ts +0 -435
  225. package/src/core/plugins/examples/analytics-plugin.ts +0 -241
  226. package/src/core/plugins/index.ts +0 -39
  227. package/src/core/plugins/registry.ts +0 -546
  228. package/src/core/plugins/types.ts +0 -169
  229. package/src/core/plugins/utils.ts +0 -317
  230. package/src/core/progressive-loading.tsx +0 -331
  231. package/src/core/providers/enhanced-hls-provider.ts +0 -307
  232. package/src/core/providers/lazy-provider.tsx +0 -14
  233. package/src/core/providers/service-provider.tsx +0 -164
  234. package/src/core/utils.tsx +0 -34
  235. package/src/features/media-session/media-session-manager.ts +0 -411
  236. package/src/features/picture-in-picture/pip-manager.ts +0 -428
  237. package/src/features/playlist/playlist-manager.ts +0 -626
  238. package/src/features/subtitles/subtitle-manager.ts +0 -435
  239. package/src/features/subtitles/subtitle-parser.ts +0 -284
  240. package/src/features/thumbnails/thumbnail-generator.ts +0 -528
  241. package/src/hooks/__tests__/currentTime-fix.test.ts +0 -149
  242. package/src/hooks/__tests__/use-media-player.test.ts +0 -712
  243. package/src/hooks/__tests__/use-media-state.test.tsx +0 -316
  244. package/src/hooks/accessibility/index.ts +0 -27
  245. package/src/hooks/accessibility/use-accessibility-preferences.ts +0 -190
  246. package/src/hooks/accessibility/use-focus-management.ts +0 -183
  247. package/src/hooks/accessibility/use-keyboard-shortcuts.ts +0 -152
  248. package/src/hooks/accessibility/use-screen-reader.ts +0 -212
  249. package/src/hooks/core/index.ts +0 -47
  250. package/src/hooks/legacy.ts +0 -21
  251. package/src/hooks/use-buffer-health.ts +0 -218
  252. package/src/hooks/use-enhanced-media-player.ts +0 -575
  253. package/src/hooks/use-focus-trap.tsx +0 -162
  254. package/src/hooks/use-intelligent-preloading.ts +0 -387
  255. package/src/hooks/use-keyboard-controls.ts +0 -115
  256. package/src/hooks/use-keyboard-shortcuts.ts +0 -255
  257. package/src/hooks/use-media-actions.ts +0 -184
  258. package/src/hooks/use-media-metadata.ts +0 -91
  259. package/src/hooks/use-media-optimistic.ts +0 -264
  260. package/src/hooks/use-media-player.ts +0 -343
  261. package/src/hooks/use-media-state.ts +0 -194
  262. package/src/hooks/use-memory-optimization.ts +0 -360
  263. package/src/hooks/use-network-status.ts +0 -124
  264. package/src/hooks/use-optimistic-controls.ts +0 -95
  265. package/src/hooks/use-optimized-media.ts +0 -283
  266. package/src/hooks/use-smart-preload.ts +0 -229
  267. package/src/hooks/use-touch-gestures.ts +0 -461
  268. package/src/hooks/useEnhancedSubtitles.ts +0 -258
  269. package/src/hooks/useKeyboardShortcuts.ts +0 -106
  270. package/src/hooks/useMediaControls.ts +0 -52
  271. package/src/hooks/useScreenshot.ts +0 -77
  272. package/src/hooks/useSubtitles.ts +0 -91
  273. package/src/hooks/useVideoPlayer.ts +0 -278
  274. package/src/icons/components/FullscreenIcon.tsx +0 -36
  275. package/src/icons/components/SettingsIcon.tsx +0 -37
  276. package/src/icons/components/animated/LoadingIcon.tsx +0 -27
  277. package/src/icons/components/animated/PlayPauseIcon.tsx +0 -42
  278. package/src/icons/components/media/PauseIcon.tsx +0 -38
  279. package/src/icons/components/media/PlayIcon.tsx +0 -37
  280. package/src/icons/components/volume/VolumeIcon.tsx +0 -38
  281. package/src/icons/components/volume/VolumeOffIcon.tsx +0 -38
  282. package/src/icons/index.ts +0 -56
  283. package/src/icons/provider.tsx +0 -58
  284. package/src/icons/types.ts +0 -60
  285. package/src/index-enhanced.ts +0 -35
  286. package/src/index-legacy.ts +0 -324
  287. package/src/index.css +0 -102
  288. package/src/lib/__tests__/async-utils.test.ts +0 -291
  289. package/src/lib/async-utils.ts +0 -194
  290. package/src/lib/deprecation.ts +0 -51
  291. package/src/lib/format-time.ts +0 -37
  292. package/src/lib/index.ts +0 -4
  293. package/src/lib/utils.ts +0 -6
  294. package/src/styles/globals.css +0 -462
  295. package/src/styles/minimal-player.css +0 -621
  296. package/src/styles/pixel-art.css +0 -41
  297. package/src/styles/videojs.css +0 -100
  298. package/src/types/assets.d.ts +0 -29
  299. package/src/types/events.ts +0 -47
  300. package/src/types/formats.ts +0 -79
  301. package/src/types/index.ts +0 -203
  302. package/src/types/videojs-plugins.d.ts +0 -14
@@ -1,398 +0,0 @@
1
- "use client"
2
-
3
- import React from "react"
4
- import type { MediaActionType } from "./media-context"
5
- import type { OptimisticMediaAction } from "./media-store"
6
-
7
- // Error types specific to media operations
8
- export enum MediaErrorType {
9
- NETWORK_ERROR = "NETWORK_ERROR",
10
- PLAYBACK_ERROR = "PLAYBACK_ERROR",
11
- PERMISSION_ERROR = "PERMISSION_ERROR",
12
- NOT_SUPPORTED_ERROR = "NOT_SUPPORTED_ERROR",
13
- TIMEOUT_ERROR = "TIMEOUT_ERROR",
14
- UNKNOWN_ERROR = "UNKNOWN_ERROR"
15
- }
16
-
17
- // Enhanced error interface
18
- export interface MediaError {
19
- type: MediaErrorType
20
- message: string
21
- action?: OptimisticMediaAction
22
- timestamp: number
23
- retryable: boolean
24
- retryCount: number
25
- originalError?: Error
26
- }
27
-
28
- // Retry configuration
29
- export interface RetryConfig {
30
- maxRetries: number
31
- baseDelay: number // milliseconds
32
- maxDelay: number // milliseconds
33
- exponentialBackoff: boolean
34
- retryableErrors: MediaErrorType[]
35
- retryableActions: MediaActionType[]
36
- }
37
-
38
- // Default retry configuration
39
- const DEFAULT_RETRY_CONFIG: RetryConfig = {
40
- maxRetries: 3,
41
- baseDelay: 1000,
42
- maxDelay: 10000,
43
- exponentialBackoff: true,
44
- retryableErrors: [MediaErrorType.NETWORK_ERROR, MediaErrorType.TIMEOUT_ERROR],
45
- retryableActions: ["PLAY", "PAUSE", "SEEK", "SET_VOLUME", "ENTER_FULLSCREEN", "EXIT_FULLSCREEN"]
46
- }
47
-
48
- // Error recovery strategies
49
- export interface ErrorRecoveryStrategy {
50
- canRecover(error: MediaError): boolean
51
- recover(error: MediaError): Promise<void>
52
- }
53
-
54
- // Network error recovery
55
- class NetworkErrorRecovery implements ErrorRecoveryStrategy {
56
- canRecover(error: MediaError): boolean {
57
- return error.type === MediaErrorType.NETWORK_ERROR && error.retryCount < 3
58
- }
59
-
60
- async recover(error: MediaError): Promise<void> {
61
- // Wait for network to become available
62
- if (navigator.onLine === false) {
63
- await new Promise((resolve) => {
64
- const handleOnline = () => {
65
- window.removeEventListener("online", handleOnline)
66
- resolve(void 0)
67
- }
68
- window.addEventListener("online", handleOnline)
69
- })
70
- }
71
-
72
- // Additional delay for network stability
73
- await new Promise((resolve) => setTimeout(resolve, 2000))
74
- }
75
- }
76
-
77
- // Playback error recovery
78
- class PlaybackErrorRecovery implements ErrorRecoveryStrategy {
79
- canRecover(error: MediaError): boolean {
80
- return error.type === MediaErrorType.PLAYBACK_ERROR && error.retryCount < 2
81
- }
82
-
83
- async recover(error: MediaError): Promise<void> {
84
- // Try to reload the media element
85
- const mediaElement = document.querySelector("video, audio") as HTMLMediaElement
86
- if (mediaElement) {
87
- mediaElement.load()
88
- await new Promise((resolve) => {
89
- const handleCanPlay = () => {
90
- mediaElement.removeEventListener("canplay", handleCanPlay)
91
- resolve(void 0)
92
- }
93
- mediaElement.addEventListener("canplay", handleCanPlay)
94
- })
95
- }
96
- }
97
- }
98
-
99
- // Permission error recovery (for fullscreen, etc.)
100
- class PermissionErrorRecovery implements ErrorRecoveryStrategy {
101
- canRecover(error: MediaError): boolean {
102
- return (
103
- error.type === MediaErrorType.PERMISSION_ERROR && error.action?.type === "ENTER_FULLSCREEN"
104
- )
105
- }
106
-
107
- async recover(error: MediaError): Promise<void> {
108
- // Request user interaction for fullscreen
109
- console.warn("Fullscreen requires user interaction")
110
- // In a real implementation, you might show a message to the user
111
- }
112
- }
113
-
114
- // Error handler class
115
- export class MediaErrorHandler {
116
- private config: RetryConfig
117
- private recoveryStrategies: ErrorRecoveryStrategy[]
118
- private errorQueue: Map<string, MediaError> = new Map()
119
- private listeners: Set<(error: MediaError) => void> = new Set()
120
-
121
- constructor(config: Partial<RetryConfig> = {}, recoveryStrategies: ErrorRecoveryStrategy[] = []) {
122
- this.config = { ...DEFAULT_RETRY_CONFIG, ...config }
123
- this.recoveryStrategies = [
124
- new NetworkErrorRecovery(),
125
- new PlaybackErrorRecovery(),
126
- new PermissionErrorRecovery(),
127
- ...recoveryStrategies
128
- ]
129
- }
130
-
131
- // Create a media error from a generic error
132
- createMediaError(error: unknown, action?: OptimisticMediaAction, retryCount = 0): MediaError {
133
- const timestamp = Date.now()
134
-
135
- if (error instanceof Error) {
136
- const errorType = this.categorizeError(error, action)
137
- return {
138
- type: errorType,
139
- message: error.message,
140
- action,
141
- timestamp,
142
- retryable: this.isRetryable(errorType, action),
143
- retryCount,
144
- originalError: error
145
- }
146
- }
147
-
148
- return {
149
- type: MediaErrorType.UNKNOWN_ERROR,
150
- message: typeof error === "string" ? error : "Unknown error occurred",
151
- action,
152
- timestamp,
153
- retryable: this.isRetryable(MediaErrorType.UNKNOWN_ERROR, action),
154
- retryCount
155
- }
156
- }
157
-
158
- // Categorize errors based on error properties and action context
159
- private categorizeError(error: Error, action?: OptimisticMediaAction): MediaErrorType {
160
- const message = error.message.toLowerCase()
161
-
162
- // Network-related errors
163
- if (
164
- message.includes("network") ||
165
- message.includes("fetch") ||
166
- message.includes("connection") ||
167
- error.name === "NetworkError"
168
- ) {
169
- return MediaErrorType.NETWORK_ERROR
170
- }
171
-
172
- // Permission errors
173
- if (
174
- message.includes("permission") ||
175
- message.includes("denied") ||
176
- message.includes("fullscreen") ||
177
- error.name === "NotAllowedError"
178
- ) {
179
- return MediaErrorType.PERMISSION_ERROR
180
- }
181
-
182
- // Playback errors
183
- if (
184
- message.includes("decode") ||
185
- message.includes("format") ||
186
- message.includes("codec") ||
187
- action?.type === "PLAY"
188
- ) {
189
- return MediaErrorType.PLAYBACK_ERROR
190
- }
191
-
192
- // Timeout errors
193
- if (message.includes("timeout") || error.name === "TimeoutError") {
194
- return MediaErrorType.TIMEOUT_ERROR
195
- }
196
-
197
- // Not supported errors
198
- if (
199
- message.includes("not supported") ||
200
- message.includes("unsupported") ||
201
- error.name === "NotSupportedError"
202
- ) {
203
- return MediaErrorType.NOT_SUPPORTED_ERROR
204
- }
205
-
206
- return MediaErrorType.UNKNOWN_ERROR
207
- }
208
-
209
- // Check if an error/action combination is retryable
210
- private isRetryable(errorType: MediaErrorType, action?: OptimisticMediaAction): boolean {
211
- const errorRetryable = this.config.retryableErrors.includes(errorType)
212
- const actionRetryable = !action || this.config.retryableActions.includes(action.type)
213
- return errorRetryable && actionRetryable
214
- }
215
-
216
- // Calculate retry delay with exponential backoff
217
- private calculateRetryDelay(retryCount: number): number {
218
- if (!this.config.exponentialBackoff) {
219
- return this.config.baseDelay
220
- }
221
-
222
- const delay = this.config.baseDelay * Math.pow(2, retryCount)
223
- return Math.min(delay, this.config.maxDelay)
224
- }
225
-
226
- // Handle an error with automatic retry logic
227
- async handleError(
228
- error: unknown,
229
- action?: OptimisticMediaAction,
230
- retryCallback?: (action: OptimisticMediaAction) => Promise<void>
231
- ): Promise<MediaError> {
232
- const mediaError = this.createMediaError(error, action, action?.retryCount || 0)
233
- const errorId = `${action?.type}-${mediaError.timestamp}`
234
-
235
- // Store error for tracking
236
- this.errorQueue.set(errorId, mediaError)
237
-
238
- // Notify listeners
239
- this.listeners.forEach((listener) => listener(mediaError))
240
-
241
- // Try recovery strategies
242
- for (const strategy of this.recoveryStrategies) {
243
- if (strategy.canRecover(mediaError)) {
244
- try {
245
- await strategy.recover(mediaError)
246
- break
247
- } catch (recoveryError) {
248
- console.warn("Recovery strategy failed:", recoveryError)
249
- }
250
- }
251
- }
252
-
253
- // Retry if possible
254
- if (
255
- mediaError.retryable &&
256
- mediaError.retryCount < this.config.maxRetries &&
257
- retryCallback &&
258
- action
259
- ) {
260
- const delay = this.calculateRetryDelay(mediaError.retryCount)
261
- console.log(
262
- `Retrying action ${action.type} in ${delay}ms (attempt ${mediaError.retryCount + 1}/${this.config.maxRetries})`
263
- )
264
-
265
- setTimeout(async () => {
266
- try {
267
- await retryCallback({
268
- ...action,
269
- retryCount: mediaError.retryCount + 1
270
- })
271
-
272
- // Remove from error queue on successful retry
273
- this.errorQueue.delete(errorId)
274
- } catch (retryError) {
275
- // Handle retry failure
276
- await this.handleError(
277
- retryError,
278
- {
279
- ...action,
280
- retryCount: mediaError.retryCount + 1
281
- },
282
- retryCallback
283
- )
284
- }
285
- }, delay)
286
- }
287
-
288
- return mediaError
289
- }
290
-
291
- // Subscribe to error events
292
- subscribe(listener: (error: MediaError) => void): () => void {
293
- this.listeners.add(listener)
294
- return () => this.listeners.delete(listener)
295
- }
296
-
297
- // Get current errors
298
- getErrors(): MediaError[] {
299
- return Array.from(this.errorQueue.values())
300
- }
301
-
302
- // Clear specific error
303
- clearError(errorId: string): void {
304
- this.errorQueue.delete(errorId)
305
- }
306
-
307
- // Clear all errors
308
- clearAllErrors(): void {
309
- this.errorQueue.clear()
310
- }
311
-
312
- // Get error statistics
313
- getErrorStats(): {
314
- totalErrors: number
315
- errorsByType: Record<MediaErrorType, number>
316
- retryableErrors: number
317
- recentErrors: MediaError[]
318
- } {
319
- const errors = this.getErrors()
320
- const now = Date.now()
321
- const recentThreshold = 5 * 60 * 1000 // 5 minutes
322
-
323
- const errorsByType = errors.reduce(
324
- (acc, error) => {
325
- acc[error.type] = (acc[error.type] || 0) + 1
326
- return acc
327
- },
328
- {} as Record<MediaErrorType, number>
329
- )
330
-
331
- const retryableErrors = errors.filter((e) => e.retryable).length
332
- const recentErrors = errors.filter((e) => now - e.timestamp < recentThreshold)
333
-
334
- return {
335
- totalErrors: errors.length,
336
- errorsByType,
337
- retryableErrors,
338
- recentErrors
339
- }
340
- }
341
- }
342
-
343
- // Hook for using error handling in components
344
- export function useMediaErrorHandler(config?: Partial<RetryConfig>) {
345
- const [handler] = React.useState(() => new MediaErrorHandler(config))
346
- const [errors, setErrors] = React.useState<MediaError[]>([])
347
-
348
- React.useEffect(() => {
349
- const unsubscribe = handler.subscribe((error) => {
350
- setErrors((current) => [...current, error])
351
- })
352
-
353
- return unsubscribe
354
- }, [handler])
355
-
356
- const clearError = React.useCallback(
357
- (errorId: string) => {
358
- handler.clearError(errorId)
359
- setErrors((current) => current.filter((e) => `${e.action?.type}-${e.timestamp}` !== errorId))
360
- },
361
- [handler]
362
- )
363
-
364
- const clearAllErrors = React.useCallback(() => {
365
- handler.clearAllErrors()
366
- setErrors([])
367
- }, [handler])
368
-
369
- return {
370
- handler,
371
- errors,
372
- clearError,
373
- clearAllErrors,
374
- errorStats: handler.getErrorStats()
375
- }
376
- }
377
-
378
- // Hook for error boundaries
379
- export function useMediaErrorBoundary() {
380
- const [error, setError] = React.useState<MediaError | null>(null)
381
-
382
- const resetError = React.useCallback(() => {
383
- setError(null)
384
- }, [])
385
-
386
- const captureError = React.useCallback((error: unknown, action?: OptimisticMediaAction) => {
387
- const handler = new MediaErrorHandler()
388
- const mediaError = handler.createMediaError(error, action)
389
- setError(mediaError)
390
- }, [])
391
-
392
- return {
393
- error,
394
- hasError: !!error,
395
- resetError,
396
- captureError
397
- }
398
- }
@@ -1,254 +0,0 @@
1
- "use client"
2
-
3
- import React from "react"
4
-
5
- // Media action types
6
- export const MediaActionTypes = {
7
- PLAY: "PLAY",
8
- PAUSE: "PAUSE",
9
- SEEK: "SEEK",
10
- SET_VOLUME: "SET_VOLUME",
11
- MUTE: "MUTE",
12
- UNMUTE: "UNMUTE",
13
- TOGGLE_MUTE: "TOGGLE_MUTE",
14
- SET_DURATION: "SET_DURATION",
15
- SET_CURRENT_TIME: "SET_CURRENT_TIME",
16
- SET_BUFFERED: "SET_BUFFERED",
17
- SET_LOADING: "SET_LOADING",
18
- SET_ERROR: "SET_ERROR",
19
- ENTER_FULLSCREEN: "ENTER_FULLSCREEN",
20
- EXIT_FULLSCREEN: "EXIT_FULLSCREEN",
21
- ENTER_PIP: "ENTER_PIP",
22
- EXIT_PIP: "EXIT_PIP",
23
- SET_PLAYBACK_RATE: "SET_PLAYBACK_RATE",
24
- SET_SUBTITLE_TRACK: "SET_SUBTITLE_TRACK",
25
- SET_RENDITION: "SET_RENDITION",
26
- TOGGLE_SUBTITLES: "TOGGLE_SUBTITLES",
27
- PREVIEW_TIME: "PREVIEW_TIME",
28
- CLEAR_PREVIEW: "CLEAR_PREVIEW",
29
- // New actions for Video.js adapter
30
- SET_BUFFERING: "SET_BUFFERING",
31
- SET_QUALITY_LEVEL: "SET_QUALITY_LEVEL",
32
- SET_BANDWIDTH_ESTIMATE: "SET_BANDWIDTH_ESTIMATE",
33
- SET_ACTIVE_TEXT_TRACKS: "SET_ACTIVE_TEXT_TRACKS"
34
- } as const
35
-
36
- export type MediaActionType = (typeof MediaActionTypes)[keyof typeof MediaActionTypes]
37
-
38
- // Media state interface
39
- export interface MediaState {
40
- // Playback state
41
- isPlaying: boolean
42
- currentTime: number
43
- duration: number
44
- buffered: TimeRanges | null
45
- isLoading: boolean
46
- isBuffering: boolean
47
- error: string | null
48
-
49
- // Audio state
50
- volume: number
51
- isMuted: boolean
52
-
53
- // Video state
54
- isFullscreen: boolean
55
- isPictureInPicture: boolean
56
-
57
- // Advanced features
58
- playbackRate: number
59
- subtitlesShowing: boolean
60
- selectedSubtitleTrack: TextTrack | null
61
- selectedRendition: string | null
62
- qualityLevel: number
63
- bandwidthEstimate: number
64
- activeTextTracks: any[]
65
-
66
- // Preview state (for seek preview)
67
- previewTime: number | null
68
- previewImage: string | null
69
- previewCoords: { x: number; y: number; width: number; height: number } | null
70
-
71
- // Media lists
72
- subtitlesList: TextTrack[]
73
- renditionList: Array<{ id: string; label: string; width?: number; height?: number }>
74
- }
75
-
76
- // Media action interface
77
- export interface MediaAction {
78
- type: MediaActionType
79
- detail?: any
80
- }
81
-
82
- // Media context interface
83
- export interface MediaContextValue {
84
- mediaId: string
85
- labelId: string
86
- descriptionId: string
87
- dir?: "ltr" | "rtl"
88
- rootRef: React.RefObject<HTMLDivElement | null>
89
- mediaRef: React.RefObject<HTMLVideoElement | HTMLAudioElement | null>
90
- portalContainer?: HTMLElement
91
- tooltipDelayDuration: number
92
- tooltipSideOffset: number
93
- disabled: boolean
94
- isVideo: boolean
95
- withoutTooltip: boolean
96
- }
97
-
98
- // Store interface for internal state management
99
- export interface MediaStore {
100
- subscribe: (callback: () => void) => () => void
101
- getState: () => MediaState
102
- setState: (updates: Partial<MediaState>) => void
103
- dispatch: (action: MediaAction) => void
104
- }
105
-
106
- // Create the media context
107
- export const MediaContext = React.createContext<MediaContextValue | null>(null)
108
-
109
- // Hook to use media context
110
- export function useMediaContext() {
111
- const context = React.useContext(MediaContext)
112
- if (!context) {
113
- throw new Error("useMediaContext must be used within a MediaPlayer")
114
- }
115
- return context
116
- }
117
-
118
- // Store context for state management
119
- export const MediaStoreContext = React.createContext<MediaStore | null>(null)
120
-
121
- // Hook to use media store
122
- export function useMediaStore() {
123
- const store = React.useContext(MediaStoreContext)
124
- if (!store) {
125
- throw new Error("useMediaStore must be used within a MediaPlayer")
126
- }
127
- return store
128
- }
129
-
130
- // Shallow comparison for selector optimization
131
- function shallowEqual(prev: unknown, next: unknown): boolean {
132
- if (Object.is(prev, next)) return true
133
-
134
- if (typeof prev !== "object" || prev === null || typeof next !== "object" || next === null) {
135
- return false
136
- }
137
-
138
- const prevKeys = Object.keys(prev as object)
139
- const nextKeys = Object.keys(next as object)
140
-
141
- if (prevKeys.length !== nextKeys.length) return false
142
-
143
- for (const key of prevKeys) {
144
- if (!nextKeys.includes(key)) return false
145
-
146
- const prevValue = (prev as Record<string, unknown>)[key]
147
- const nextValue = (next as Record<string, unknown>)[key]
148
-
149
- if (!Object.is(prevValue, nextValue)) return false
150
- }
151
-
152
- return true
153
- }
154
-
155
- // Hook to select specific state values - React 19 optimized with shallow comparison
156
- export function useMediaSelector<T>(selector: (state: MediaState) => T): T {
157
- const store = useMediaStore()
158
-
159
- // React 19 compiler will optimize this callback
160
- const getSnapshot = () => selector(store.getState())
161
-
162
- // Track previous selected value for shallow comparison
163
- const prevRef = React.useRef<T | undefined>(undefined)
164
- const getServerSnapshot = React.useCallback(() => {
165
- const value = selector(store.getState())
166
- prevRef.current = value
167
- return value
168
- }, [selector])
169
-
170
- // Use useSyncExternalStore for subscription
171
- const selected = React.useSyncExternalStore(store.subscribe, getSnapshot, getServerSnapshot)
172
-
173
- // Apply shallow comparison to prevent unnecessary re-renders
174
- React.useEffect(() => {
175
- const prev = prevRef.current
176
- if (prev !== undefined && shallowEqual(prev, selected)) {
177
- // Values are equal, no re-render needed
178
- return
179
- }
180
- prevRef.current = selected
181
- }, [selected])
182
-
183
- return selected
184
- }
185
-
186
- // Hook to get dispatch function
187
- export function useMediaDispatch() {
188
- const store = useMediaStore()
189
- return store.dispatch
190
- }
191
-
192
- // React 19 enhanced context selector with optimistic updates
193
- export function useOptimisticMediaSelector<T>(selector: (state: MediaState) => T): T {
194
- const store = useMediaStore()
195
-
196
- // Check if enhanced store is available
197
- const isEnhanced = "getOptimisticState" in store
198
-
199
- const getSnapshot = () => {
200
- if (isEnhanced) {
201
- // Use optimistic state for immediate UI feedback
202
- return selector((store as any).getOptimisticState())
203
- } else {
204
- // Fall back to regular state
205
- return selector(store.getState())
206
- }
207
- }
208
-
209
- return React.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot)
210
- }
211
-
212
- // Hook for accessing React 19 enhanced features
213
- export function useMediaEnhancements() {
214
- const store = useMediaStore()
215
- const context = useMediaContext()
216
-
217
- const isEnhanced = "getOptimisticState" in store
218
- const errorHandler = "errorHandler" in context ? (context as any).errorHandler : null
219
- const isRehydrated = "isRehydrated" in context ? (context as any).isRehydrated : true
220
-
221
- return {
222
- isEnhanced,
223
- errorHandler,
224
- isRehydrated,
225
- actionsState: isEnhanced ? (store as any).getActionState() : null
226
- }
227
- }
228
-
229
- // Initial media state
230
- export const initialMediaState: MediaState = {
231
- isPlaying: false,
232
- currentTime: 0,
233
- duration: 0,
234
- buffered: null,
235
- isLoading: false,
236
- isBuffering: false,
237
- error: null,
238
- volume: 1,
239
- isMuted: false,
240
- isFullscreen: false,
241
- isPictureInPicture: false,
242
- playbackRate: 1,
243
- subtitlesShowing: false,
244
- selectedSubtitleTrack: null,
245
- selectedRendition: null,
246
- qualityLevel: -1,
247
- bandwidthEstimate: 0,
248
- activeTextTracks: [],
249
- previewTime: null,
250
- previewImage: null,
251
- previewCoords: null,
252
- subtitlesList: [],
253
- renditionList: []
254
- }