@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,545 +0,0 @@
1
- import React from "react"
2
-
3
- // Network monitoring and adaptive loading
4
- export interface NetworkInfo {
5
- effectiveType: "2g" | "3g" | "4g" | "5g" | "unknown"
6
- downlink: number // Mbps
7
- rtt: number // Round trip time in ms
8
- saveData: boolean
9
- isOnline: boolean
10
- }
11
-
12
- export interface MediaLoadingConfig {
13
- preloadStrategy: "none" | "metadata" | "auto"
14
- adaptiveBitrate: boolean
15
- maxPreloadSize: number // bytes
16
- networkThresholds: {
17
- "2g": { maxBitrate: number; preload: boolean }
18
- "3g": { maxBitrate: number; preload: boolean }
19
- "4g": { maxBitrate: number; preload: boolean }
20
- "5g": { maxBitrate: number; preload: boolean }
21
- }
22
- bufferSize: number // seconds
23
- enableServiceWorker: boolean
24
- }
25
-
26
- export const defaultMediaLoadingConfig: MediaLoadingConfig = {
27
- preloadStrategy: "metadata",
28
- adaptiveBitrate: true,
29
- maxPreloadSize: 2 * 1024 * 1024, // 2MB
30
- networkThresholds: {
31
- "2g": { maxBitrate: 128, preload: false }, // 128 kbps
32
- "3g": { maxBitrate: 500, preload: false }, // 500 kbps
33
- "4g": { maxBitrate: 2000, preload: true }, // 2 Mbps
34
- "5g": { maxBitrate: 10000, preload: true } // 10 Mbps
35
- },
36
- bufferSize: 10, // 10 seconds
37
- enableServiceWorker: true
38
- }
39
-
40
- // Media loading performance tracker
41
- export interface MediaLoadingMetrics {
42
- loadStartTime: number
43
- firstByteTime?: number
44
- loadCompleteTime?: number
45
- totalLoadTime?: number
46
- bytesLoaded: number
47
- loadSpeed: number // bytes per second
48
- networkType: string
49
- quality: string
50
- bufferHealth: number // 0-1 scale
51
- stallsCount: number
52
- stallsDuration: number
53
- }
54
-
55
- // Network monitoring utility
56
- export class NetworkMonitor {
57
- private connection: any
58
- private listeners: Set<(info: NetworkInfo) => void> = new Set()
59
- private currentInfo: NetworkInfo
60
-
61
- constructor() {
62
- if (typeof window === "undefined" || typeof navigator === "undefined") {
63
- // Server-side rendering fallback
64
- this.connection = null
65
- this.currentInfo = {
66
- effectiveType: "unknown",
67
- downlink: 0,
68
- rtt: 0,
69
- saveData: false,
70
- isOnline: true
71
- }
72
- return
73
- }
74
-
75
- this.connection =
76
- (navigator as any).connection ||
77
- (navigator as any).mozConnection ||
78
- (navigator as any).webkitConnection
79
-
80
- this.currentInfo = this.getNetworkInfo()
81
- this.initializeListeners()
82
- }
83
-
84
- private getNetworkInfo(): NetworkInfo {
85
- if (typeof navigator === "undefined") {
86
- // Server-side rendering fallback
87
- return {
88
- effectiveType: "unknown",
89
- downlink: 0,
90
- rtt: 0,
91
- saveData: false,
92
- isOnline: true
93
- }
94
- }
95
-
96
- const isOnline = navigator.onLine
97
-
98
- if (this.connection) {
99
- return {
100
- effectiveType: this.connection.effectiveType || "unknown",
101
- downlink: this.connection.downlink || 0,
102
- rtt: this.connection.rtt || 0,
103
- saveData: this.connection.saveData || false,
104
- isOnline
105
- }
106
- }
107
-
108
- // Fallback for browsers without Network Information API
109
- return {
110
- effectiveType: "unknown",
111
- downlink: 0,
112
- rtt: 0,
113
- saveData: false,
114
- isOnline
115
- }
116
- }
117
-
118
- private initializeListeners() {
119
- if (typeof window === "undefined") {
120
- // Server-side rendering - skip event listeners
121
- return
122
- }
123
-
124
- if (this.connection) {
125
- this.connection.addEventListener("change", this.handleNetworkChange.bind(this))
126
- }
127
-
128
- window.addEventListener("online", this.handleNetworkChange.bind(this))
129
- window.addEventListener("offline", this.handleNetworkChange.bind(this))
130
- }
131
-
132
- private handleNetworkChange() {
133
- const newInfo = this.getNetworkInfo()
134
- this.currentInfo = newInfo
135
- this.listeners.forEach((listener) => listener(newInfo))
136
- }
137
-
138
- getCurrentNetworkInfo(): NetworkInfo {
139
- return { ...this.currentInfo }
140
- }
141
-
142
- subscribe(listener: (info: NetworkInfo) => void): () => void {
143
- this.listeners.add(listener)
144
- return () => this.listeners.delete(listener)
145
- }
146
-
147
- // Estimate available bandwidth with fallback detection
148
- async estimateBandwidth(): Promise<number> {
149
- if (this.connection && this.connection.downlink) {
150
- return this.connection.downlink * 1000 // Convert to kbps
151
- }
152
-
153
- // Fallback: simple bandwidth test
154
- try {
155
- const startTime = performance.now()
156
- const testUrl = "/api/bandwidth-test?size=100kb" // Would need to be implemented
157
- const response = await fetch(testUrl)
158
- const blob = await response.blob()
159
- const endTime = performance.now()
160
-
161
- const timeInSeconds = (endTime - startTime) / 1000
162
- const bytesLoaded = blob.size
163
- const bitsPerSecond = (bytesLoaded * 8) / timeInSeconds
164
-
165
- return bitsPerSecond / 1000 // Return in kbps
166
- } catch (error) {
167
- console.warn("Bandwidth estimation failed:", error)
168
- return 1000 // Default to 1Mbps
169
- }
170
- }
171
- }
172
-
173
- // Media loading optimizer
174
- export class MediaLoadingOptimizer {
175
- private config: MediaLoadingConfig
176
- private networkMonitor: NetworkMonitor
177
- private loadingMetrics: Map<string, MediaLoadingMetrics> = new Map()
178
- private preloadCache: Map<string, Promise<Blob>> = new Map()
179
-
180
- constructor(config: Partial<MediaLoadingConfig> = {}) {
181
- this.config = { ...defaultMediaLoadingConfig, ...config }
182
- this.networkMonitor = new NetworkMonitor()
183
- this.initializeNetworkMonitoring()
184
- }
185
-
186
- private initializeNetworkMonitoring() {
187
- this.networkMonitor.subscribe((networkInfo) => {
188
- this.handleNetworkChange(networkInfo)
189
- })
190
- }
191
-
192
- private handleNetworkChange(networkInfo: NetworkInfo) {
193
- console.log("Network changed:", networkInfo)
194
-
195
- // Adjust quality based on network conditions
196
- if (this.config.adaptiveBitrate) {
197
- this.adjustQualityForNetwork(networkInfo)
198
- }
199
-
200
- // Clear preload cache if on slow network
201
- if (networkInfo.effectiveType === "2g" || networkInfo.saveData) {
202
- this.clearPreloadCache()
203
- }
204
- }
205
-
206
- // Optimize media loading based on network conditions
207
- async optimizeMediaLoading(
208
- mediaUrl: string,
209
- element: HTMLMediaElement,
210
- options: {
211
- quality?: string
212
- preload?: boolean
213
- priority?: "high" | "normal" | "low"
214
- } = {}
215
- ): Promise<MediaLoadingMetrics> {
216
- const startTime = performance.now()
217
- const networkInfo = this.networkMonitor.getCurrentNetworkInfo()
218
-
219
- const metrics: MediaLoadingMetrics = {
220
- loadStartTime: startTime,
221
- bytesLoaded: 0,
222
- loadSpeed: 0,
223
- networkType: networkInfo.effectiveType,
224
- quality: options.quality || "auto",
225
- bufferHealth: 0,
226
- stallsCount: 0,
227
- stallsDuration: 0
228
- }
229
-
230
- this.loadingMetrics.set(mediaUrl, metrics)
231
-
232
- try {
233
- // Choose optimal loading strategy
234
- const loadingStrategy = this.chooseLoadingStrategy(networkInfo, options)
235
-
236
- // Apply preload strategy
237
- if (loadingStrategy.shouldPreload) {
238
- await this.preloadMedia(mediaUrl, loadingStrategy.preloadAmount)
239
- }
240
-
241
- // Set appropriate preload attribute
242
- element.preload = loadingStrategy.preloadAttribute
243
-
244
- // Monitor loading progress
245
- this.monitorLoadingProgress(element, metrics)
246
-
247
- // Apply quality adjustments
248
- if (this.config.adaptiveBitrate && loadingStrategy.suggestedQuality) {
249
- this.applyQualitySettings(element, loadingStrategy.suggestedQuality)
250
- }
251
-
252
- return metrics
253
- } catch (error) {
254
- console.error("Media loading optimization failed:", error)
255
- return metrics
256
- }
257
- }
258
-
259
- private chooseLoadingStrategy(
260
- networkInfo: NetworkInfo,
261
- options: { preload?: boolean; priority?: string; quality?: string }
262
- ) {
263
- const effectiveType = networkInfo.effectiveType === "unknown" ? "4g" : networkInfo.effectiveType
264
- const threshold =
265
- this.config.networkThresholds[effectiveType] || this.config.networkThresholds["4g"]
266
-
267
- return {
268
- shouldPreload: options.preload !== false && threshold.preload && !networkInfo.saveData,
269
- preloadAmount: networkInfo.saveData ? 0 : this.config.maxPreloadSize,
270
- preloadAttribute: this.getPreloadAttribute(networkInfo),
271
- suggestedQuality: this.getSuggestedQuality(networkInfo, threshold.maxBitrate),
272
- bufferTarget: this.getBufferTarget(networkInfo)
273
- }
274
- }
275
-
276
- private getPreloadAttribute(networkInfo: NetworkInfo): "none" | "metadata" | "auto" {
277
- if (networkInfo.saveData || networkInfo.effectiveType === "2g") {
278
- return "none"
279
- }
280
-
281
- if (networkInfo.effectiveType === "3g") {
282
- return "metadata"
283
- }
284
-
285
- return this.config.preloadStrategy
286
- }
287
-
288
- private getSuggestedQuality(networkInfo: NetworkInfo, maxBitrate: number): string {
289
- const availableBandwidth = networkInfo.downlink * 1000 // Convert to kbps
290
-
291
- if (availableBandwidth >= maxBitrate * 2) return "high"
292
- if (availableBandwidth >= maxBitrate) return "medium"
293
- return "low"
294
- }
295
-
296
- private getBufferTarget(networkInfo: NetworkInfo): number {
297
- switch (networkInfo.effectiveType) {
298
- case "2g":
299
- return 2 // 2 seconds
300
- case "3g":
301
- return 5 // 5 seconds
302
- case "4g":
303
- return this.config.bufferSize
304
- case "5g":
305
- return this.config.bufferSize * 1.5
306
- default:
307
- return this.config.bufferSize
308
- }
309
- }
310
-
311
- // Preload media content
312
- async preloadMedia(url: string, maxSize: number): Promise<void> {
313
- if (this.preloadCache.has(url)) {
314
- return // Already preloading or preloaded
315
- }
316
-
317
- const preloadPromise = this.fetchWithProgress(url, maxSize)
318
- this.preloadCache.set(url, preloadPromise)
319
-
320
- try {
321
- await preloadPromise
322
- } catch (error) {
323
- console.warn(`Preload failed for ${url}:`, error)
324
- this.preloadCache.delete(url)
325
- }
326
- }
327
-
328
- private async fetchWithProgress(url: string, maxSize: number): Promise<Blob> {
329
- const response = await fetch(url, {
330
- headers: {
331
- Range: `bytes=0-${maxSize - 1}` // Limit preload size
332
- }
333
- })
334
-
335
- if (!response.ok) {
336
- throw new Error(`Failed to preload: ${response.status}`)
337
- }
338
-
339
- const reader = response.body?.getReader()
340
- if (!reader) {
341
- throw new Error("Response body not readable")
342
- }
343
-
344
- const chunks: Uint8Array[] = []
345
- let bytesRead = 0
346
-
347
- try {
348
- while (bytesRead < maxSize) {
349
- const { done, value } = await reader.read()
350
- if (done) break
351
-
352
- chunks.push(value)
353
- bytesRead += value.length
354
- }
355
- } finally {
356
- reader.releaseLock()
357
- }
358
-
359
- // TS 5.9+: Uint8Array generic buffer typing is stricter than BlobPart
360
- return new Blob(chunks as BlobPart[])
361
- }
362
-
363
- // Monitor loading progress and update metrics
364
- private monitorLoadingProgress(element: HTMLMediaElement, metrics: MediaLoadingMetrics) {
365
- let stallStartTime: number | null = null
366
-
367
- const updateMetrics = () => {
368
- if (element.buffered.length > 0) {
369
- const bufferedEnd = element.buffered.end(element.buffered.length - 1)
370
- const currentTime = element.currentTime
371
- metrics.bufferHealth = Math.min((bufferedEnd - currentTime) / this.config.bufferSize, 1)
372
- }
373
- }
374
-
375
- // Track first byte
376
- const onLoadStart = () => {
377
- metrics.firstByteTime = performance.now()
378
- }
379
-
380
- // Track load completion
381
- const onCanPlay = () => {
382
- metrics.loadCompleteTime = performance.now()
383
- metrics.totalLoadTime = metrics.loadCompleteTime - metrics.loadStartTime
384
-
385
- // Calculate load speed
386
- if (metrics.totalLoadTime && metrics.bytesLoaded > 0) {
387
- metrics.loadSpeed = metrics.bytesLoaded / (metrics.totalLoadTime / 1000)
388
- }
389
- }
390
-
391
- // Track stalls
392
- const onWaiting = () => {
393
- if (stallStartTime === null) {
394
- stallStartTime = performance.now()
395
- metrics.stallsCount++
396
- }
397
- }
398
-
399
- const onPlaying = () => {
400
- if (stallStartTime !== null) {
401
- metrics.stallsDuration += performance.now() - stallStartTime
402
- stallStartTime = null
403
- }
404
- updateMetrics()
405
- }
406
-
407
- // Track progress
408
- const onProgress = () => {
409
- if (element.buffered.length > 0) {
410
- const bufferedBytes = element.buffered.end(0) * 1000 // Rough estimate
411
- metrics.bytesLoaded = bufferedBytes
412
- }
413
- updateMetrics()
414
- }
415
-
416
- // Add event listeners
417
- element.addEventListener("loadstart", onLoadStart)
418
- element.addEventListener("canplay", onCanPlay)
419
- element.addEventListener("waiting", onWaiting)
420
- element.addEventListener("playing", onPlaying)
421
- element.addEventListener("progress", onProgress)
422
-
423
- // Cleanup function
424
- const cleanup = () => {
425
- element.removeEventListener("loadstart", onLoadStart)
426
- element.removeEventListener("canplay", onCanPlay)
427
- element.removeEventListener("waiting", onWaiting)
428
- element.removeEventListener("playing", onPlaying)
429
- element.removeEventListener("progress", onProgress)
430
- }
431
-
432
- // Auto-cleanup after 5 minutes
433
- setTimeout(cleanup, 5 * 60 * 1000)
434
- }
435
-
436
- // Apply quality settings (would integrate with HLS.js or similar)
437
- private applyQualitySettings(element: HTMLMediaElement, quality: string) {
438
- // This would integrate with your video streaming library
439
- console.log(`Applying quality setting: ${quality} to`, element)
440
-
441
- // Example integration with HLS.js:
442
- // if (element.hls) {
443
- // element.hls.currentLevel = this.getQualityLevel(quality);
444
- // }
445
- }
446
-
447
- private adjustQualityForNetwork(networkInfo: NetworkInfo) {
448
- // Auto-adjust quality for all active media elements
449
- console.log("Adjusting quality for network conditions:", networkInfo.effectiveType)
450
- }
451
-
452
- // Clear preload cache to save memory
453
- clearPreloadCache() {
454
- this.preloadCache.clear()
455
- }
456
-
457
- // Get loading metrics for a specific media URL
458
- getLoadingMetrics(url: string): MediaLoadingMetrics | undefined {
459
- return this.loadingMetrics.get(url)
460
- }
461
-
462
- // Get all loading metrics
463
- getAllMetrics(): MediaLoadingMetrics[] {
464
- return Array.from(this.loadingMetrics.values())
465
- }
466
-
467
- // Calculate average loading performance
468
- getAverageLoadingTime(): number {
469
- const metrics = this.getAllMetrics()
470
- const completedLoads = metrics.filter((m) => m.totalLoadTime !== undefined)
471
-
472
- if (completedLoads.length === 0) return 0
473
-
474
- const total = completedLoads.reduce((sum, m) => sum + (m.totalLoadTime || 0), 0)
475
- return total / completedLoads.length
476
- }
477
-
478
- // Get network-specific performance stats
479
- getNetworkPerformanceStats(): {
480
- networkType: string
481
- avgLoadTime: number
482
- avgStalls: number
483
- avgBufferHealth: number
484
- }[] {
485
- const statsByNetwork = new Map<string, MediaLoadingMetrics[]>()
486
-
487
- this.getAllMetrics().forEach((metrics) => {
488
- const network = metrics.networkType
489
- if (!statsByNetwork.has(network)) {
490
- statsByNetwork.set(network, [])
491
- }
492
- statsByNetwork.get(network)!.push(metrics)
493
- })
494
-
495
- return Array.from(statsByNetwork.entries()).map(([networkType, metrics]) => ({
496
- networkType,
497
- avgLoadTime: metrics.reduce((sum, m) => sum + (m.totalLoadTime || 0), 0) / metrics.length,
498
- avgStalls: metrics.reduce((sum, m) => sum + m.stallsCount, 0) / metrics.length,
499
- avgBufferHealth: metrics.reduce((sum, m) => sum + m.bufferHealth, 0) / metrics.length
500
- }))
501
- }
502
- }
503
-
504
- // Global media loading optimizer instance
505
- export const mediaLoadingOptimizer = new MediaLoadingOptimizer()
506
-
507
- // React hook for media loading optimization
508
- export function useMediaLoadingOptimizer(config?: Partial<MediaLoadingConfig>) {
509
- const [optimizer] = React.useState(() =>
510
- config ? new MediaLoadingOptimizer(config) : mediaLoadingOptimizer
511
- )
512
-
513
- const [networkInfo, setNetworkInfo] = React.useState<NetworkInfo | null>(null)
514
- const [loadingMetrics, setLoadingMetrics] = React.useState<MediaLoadingMetrics[]>([])
515
-
516
- React.useEffect(() => {
517
- const unsubscribe = optimizer["networkMonitor"].subscribe(setNetworkInfo)
518
- setNetworkInfo(optimizer["networkMonitor"].getCurrentNetworkInfo())
519
-
520
- // Update metrics periodically
521
- const interval = setInterval(() => {
522
- setLoadingMetrics(optimizer.getAllMetrics())
523
- }, 1000)
524
-
525
- return () => {
526
- unsubscribe()
527
- clearInterval(interval)
528
- }
529
- }, [optimizer])
530
-
531
- const optimizeLoading = React.useCallback(
532
- (mediaUrl: string, element: HTMLMediaElement, options?: any) => {
533
- return optimizer.optimizeMediaLoading(mediaUrl, element, options)
534
- },
535
- [optimizer]
536
- )
537
-
538
- return {
539
- networkInfo,
540
- loadingMetrics,
541
- optimizeLoading,
542
- averageLoadTime: optimizer.getAverageLoadingTime(),
543
- networkStats: optimizer.getNetworkPerformanceStats()
544
- }
545
- }