@therealtinhtute/baroiplayer 1.2.0 → 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 (305) hide show
  1. package/README.md +91 -73
  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 +2 -112
  64. package/dist/index.js.map +1 -1
  65. package/dist/index.mjs +786 -6271
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/package.json +3 -0
  68. package/package.json +110 -108
  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 -2
  78. package/dist/context/media.js.map +0 -1
  79. package/dist/context/media.mjs +0 -15
  80. package/dist/context/media.mjs.map +0 -1
  81. package/dist/context/store.js +0 -2
  82. package/dist/context/store.js.map +0 -1
  83. package/dist/context/store.mjs +0 -5
  84. package/dist/context/store.mjs.map +0 -1
  85. package/dist/context-BYwDoSRX.js +0 -1172
  86. package/dist/context-BYwDoSRX.js.map +0 -1
  87. package/dist/context-eNS62_ac.cjs +0 -23
  88. package/dist/context-eNS62_ac.cjs.map +0 -1
  89. package/dist/core-events-B1iM2F46.cjs +0 -2
  90. package/dist/core-events-B1iM2F46.cjs.map +0 -1
  91. package/dist/core-events-DunPHKRE.js +0 -484
  92. package/dist/core-events-DunPHKRE.js.map +0 -1
  93. package/dist/core-plugins-By-4-kGs.cjs +0 -2
  94. package/dist/core-plugins-By-4-kGs.cjs.map +0 -1
  95. package/dist/core-plugins-DSBWcTuX.js +0 -821
  96. package/dist/core-plugins-DSBWcTuX.js.map +0 -1
  97. package/dist/core.js +0 -37
  98. package/dist/core.js.map +0 -1
  99. package/dist/core.mjs +0 -1233
  100. package/dist/core.mjs.map +0 -1
  101. package/dist/enhanced-components-B_l3cist.js +0 -1142
  102. package/dist/enhanced-components-B_l3cist.js.map +0 -1
  103. package/dist/enhanced-components-BspFs9OO.cjs +0 -2
  104. package/dist/enhanced-components-BspFs9OO.cjs.map +0 -1
  105. package/dist/hooks-BXwI8QG6.cjs +0 -4
  106. package/dist/hooks-BXwI8QG6.cjs.map +0 -1
  107. package/dist/hooks-Bpi-jDiO.js +0 -1816
  108. package/dist/hooks-Bpi-jDiO.js.map +0 -1
  109. package/dist/minimal-components-C4z900Ro.js +0 -1926
  110. package/dist/minimal-components-C4z900Ro.js.map +0 -1
  111. package/dist/minimal-components-v4qBp6jv.cjs +0 -2
  112. package/dist/minimal-components-v4qBp6jv.cjs.map +0 -1
  113. package/dist/minimal-components.css +0 -1
  114. package/dist/mona-loading.gif +0 -0
  115. package/dist/performance-monitor-C5k6FDXw.js +0 -301
  116. package/dist/performance-monitor-C5k6FDXw.js.map +0 -1
  117. package/dist/performance-monitor-lJmuUjQQ.cjs +0 -2
  118. package/dist/performance-monitor-lJmuUjQQ.cjs.map +0 -1
  119. package/dist/utils-CFOue_9K.cjs +0 -9
  120. package/dist/utils-CFOue_9K.cjs.map +0 -1
  121. package/dist/utils-Dzpl2ArK.js +0 -2844
  122. package/dist/utils-Dzpl2ArK.js.map +0 -1
  123. package/dist/utils.js +0 -2
  124. package/dist/utils.js.map +0 -1
  125. package/dist/utils.mjs +0 -11
  126. package/dist/utils.mjs.map +0 -1
  127. package/src/adapters/videojs-adapter.tsx +0 -470
  128. package/src/assets/mona-loading.gif +0 -0
  129. package/src/components/AnimateLoading.tsx +0 -107
  130. package/src/components/LoadingState.tsx +0 -239
  131. package/src/components/__tests__/media-player-accessibility.test.tsx +0 -510
  132. package/src/components/__tests__/media-player-react19.test.tsx +0 -457
  133. package/src/components/accessibility/keyboard-help-overlay.tsx +0 -207
  134. package/src/components/audio-player.tsx +0 -85
  135. package/src/components/basic/index.ts +0 -37
  136. package/src/components/enhanced/advanced-features.tsx +0 -311
  137. package/src/components/enhanced/debug-panel.tsx +0 -448
  138. package/src/components/enhanced/enhanced-controls.tsx +0 -597
  139. package/src/components/enhanced/enhanced-media-player.tsx +0 -566
  140. package/src/components/enhanced/error-handling.tsx +0 -338
  141. package/src/components/enhanced/index.ts +0 -39
  142. package/src/components/enhanced/media-player-enhanced.tsx +0 -383
  143. package/src/components/examples/basic-video-player.tsx +0 -50
  144. package/src/components/examples/custom-controls-example.tsx +0 -63
  145. package/src/components/examples/enhanced-controls-example.tsx +0 -100
  146. package/src/components/examples/enhanced-media-player-example.tsx +0 -302
  147. package/src/components/examples/loading-states-demo.tsx +0 -142
  148. package/src/components/examples/react-19-demo.tsx +0 -353
  149. package/src/components/examples/volume-orientation-demo.tsx +0 -106
  150. package/src/components/icon-demo.tsx +0 -196
  151. package/src/components/legacy.tsx +0 -87
  152. package/src/components/media-metadata-display.tsx +0 -99
  153. package/src/components/media-player-audio.tsx +0 -39
  154. package/src/components/media-player-controls.tsx +0 -223
  155. package/src/components/media-player-error.tsx +0 -163
  156. package/src/components/media-player-fullscreen.tsx +0 -109
  157. package/src/components/media-player-hls.tsx +0 -111
  158. package/src/components/media-player-loading.tsx +0 -76
  159. package/src/components/media-player-play.tsx +0 -75
  160. package/src/components/media-player-root.tsx +0 -338
  161. package/src/components/media-player-seek.tsx +0 -168
  162. package/src/components/media-player-time.tsx +0 -99
  163. package/src/components/media-player-tooltip.tsx +0 -58
  164. package/src/components/media-player-video.tsx +0 -54
  165. package/src/components/media-player-volume.tsx +0 -155
  166. package/src/components/media-player.tsx +0 -292
  167. package/src/components/media-suspense.tsx +0 -344
  168. package/src/components/player-settings-form.tsx +0 -158
  169. package/src/components/react-player-wrapper.tsx +0 -651
  170. package/src/components/simple-video-player.tsx +0 -62
  171. package/src/components/ui/blur-poster.tsx +0 -93
  172. package/src/components/ui/empty-state.tsx +0 -91
  173. package/src/components/ui/enhanced-seek-bar.tsx +0 -254
  174. package/src/components/ui/error-state.tsx +0 -124
  175. package/src/components/ui/fullscreen-button.tsx +0 -81
  176. package/src/components/ui/loading-skeleton.tsx +0 -107
  177. package/src/components/ui/media-resource-preloader.tsx +0 -458
  178. package/src/components/ui/offline-message.tsx +0 -98
  179. package/src/components/ui/play-button.tsx +0 -99
  180. package/src/components/ui/seek-bar.tsx +0 -191
  181. package/src/components/ui/time-display.tsx +0 -61
  182. package/src/components/ui/volume-control.tsx +0 -190
  183. package/src/components/unified/base-media-player.tsx +0 -252
  184. package/src/components/unified/media-player.tsx +0 -75
  185. package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +0 -587
  186. package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +0 -573
  187. package/src/components/variants/minimal/MinimalControls.tsx +0 -124
  188. package/src/components/variants/minimal/MinimalLoading.tsx +0 -28
  189. package/src/components/variants/minimal/MinimalMediaPlayer.tsx +0 -318
  190. package/src/components/variants/minimal/MinimalOverlay.tsx +0 -58
  191. package/src/components/variants/minimal/MinimalPlayButton.tsx +0 -56
  192. package/src/components/variants/minimal/MinimalSeekBar.tsx +0 -140
  193. package/src/components/variants/minimal/MinimalVolumeControl.tsx +0 -75
  194. package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +0 -206
  195. package/src/components/variants/minimal/components/CenterPlayButton.tsx +0 -22
  196. package/src/components/variants/minimal/components/ControlBar.tsx +0 -142
  197. package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +0 -412
  198. package/src/components/variants/minimal/components/PlaybackControls.tsx +0 -46
  199. package/src/components/variants/minimal/components/RightControls.tsx +0 -164
  200. package/src/components/variants/minimal/components/SeekBar.tsx +0 -127
  201. package/src/components/variants/minimal/components/SettingsDropdown.tsx +0 -68
  202. package/src/components/variants/minimal/components/SubtitleDisplay.tsx +0 -21
  203. package/src/components/variants/minimal/components/TimeDisplay.tsx +0 -15
  204. package/src/components/variants/minimal/components/VideoElement.tsx +0 -33
  205. package/src/components/variants/minimal/components/VolumeControl.tsx +0 -220
  206. package/src/components/variants/minimal/index.ts +0 -23
  207. package/src/components/video-player.tsx +0 -100
  208. package/src/context/__tests__/media-store.test.ts +0 -509
  209. package/src/context/error-handling.ts +0 -398
  210. package/src/context/media-context.tsx +0 -254
  211. package/src/context/media-provider.tsx +0 -264
  212. package/src/context/media-store.ts +0 -387
  213. package/src/context/persistence.ts +0 -462
  214. package/src/core/events/event-system.ts +0 -448
  215. package/src/core/events/hooks.ts +0 -325
  216. package/src/core/events/index.ts +0 -22
  217. package/src/core/events/middleware.ts +0 -286
  218. package/src/core/index.ts +0 -22
  219. package/src/core/optimization/bundle-optimizer.tsx +0 -312
  220. package/src/core/performance/cicd.ts +0 -98
  221. package/src/core/performance/index.ts +0 -38
  222. package/src/core/performance/media-loading-optimizer.ts +0 -544
  223. package/src/core/performance/performance-budgets.ts +0 -437
  224. package/src/core/performance/performance-monitor.tsx +0 -488
  225. package/src/core/performance/performance-testing.ts +0 -461
  226. package/src/core/plugins/__tests__/registry.test.ts +0 -595
  227. package/src/core/plugins/base-plugin.ts +0 -225
  228. package/src/core/plugins/enhanced-plugin-system.ts +0 -435
  229. package/src/core/plugins/examples/analytics-plugin.ts +0 -241
  230. package/src/core/plugins/index.ts +0 -39
  231. package/src/core/plugins/registry.ts +0 -546
  232. package/src/core/plugins/types.ts +0 -169
  233. package/src/core/plugins/utils.ts +0 -317
  234. package/src/core/progressive-loading.tsx +0 -331
  235. package/src/core/providers/enhanced-hls-provider.ts +0 -307
  236. package/src/core/providers/lazy-provider.tsx +0 -14
  237. package/src/core/providers/service-provider.tsx +0 -164
  238. package/src/core/utils.tsx +0 -34
  239. package/src/features/media-session/media-session-manager.ts +0 -411
  240. package/src/features/picture-in-picture/pip-manager.ts +0 -428
  241. package/src/features/playlist/playlist-manager.ts +0 -626
  242. package/src/features/subtitles/subtitle-manager.ts +0 -435
  243. package/src/features/subtitles/subtitle-parser.ts +0 -284
  244. package/src/features/thumbnails/thumbnail-generator.ts +0 -528
  245. package/src/hooks/__tests__/currentTime-fix.test.ts +0 -149
  246. package/src/hooks/__tests__/use-media-player.test.ts +0 -712
  247. package/src/hooks/__tests__/use-media-state.test.tsx +0 -316
  248. package/src/hooks/accessibility/index.ts +0 -27
  249. package/src/hooks/accessibility/use-accessibility-preferences.ts +0 -190
  250. package/src/hooks/accessibility/use-focus-management.ts +0 -183
  251. package/src/hooks/accessibility/use-keyboard-shortcuts.ts +0 -152
  252. package/src/hooks/accessibility/use-screen-reader.ts +0 -212
  253. package/src/hooks/core/index.ts +0 -47
  254. package/src/hooks/legacy.ts +0 -21
  255. package/src/hooks/use-buffer-health.ts +0 -218
  256. package/src/hooks/use-enhanced-media-player.ts +0 -575
  257. package/src/hooks/use-focus-trap.tsx +0 -162
  258. package/src/hooks/use-intelligent-preloading.ts +0 -387
  259. package/src/hooks/use-keyboard-controls.ts +0 -115
  260. package/src/hooks/use-keyboard-shortcuts.ts +0 -255
  261. package/src/hooks/use-media-actions.ts +0 -184
  262. package/src/hooks/use-media-metadata.ts +0 -91
  263. package/src/hooks/use-media-optimistic.ts +0 -264
  264. package/src/hooks/use-media-player.ts +0 -343
  265. package/src/hooks/use-media-state.ts +0 -194
  266. package/src/hooks/use-memory-optimization.ts +0 -360
  267. package/src/hooks/use-network-status.ts +0 -124
  268. package/src/hooks/use-optimistic-controls.ts +0 -95
  269. package/src/hooks/use-optimized-media.ts +0 -283
  270. package/src/hooks/use-smart-preload.ts +0 -229
  271. package/src/hooks/use-touch-gestures.ts +0 -461
  272. package/src/hooks/useEnhancedSubtitles.ts +0 -258
  273. package/src/hooks/useKeyboardShortcuts.ts +0 -106
  274. package/src/hooks/useMediaControls.ts +0 -52
  275. package/src/hooks/useScreenshot.ts +0 -61
  276. package/src/hooks/useSubtitles.ts +0 -91
  277. package/src/hooks/useVideoPlayer.ts +0 -278
  278. package/src/icons/components/FullscreenIcon.tsx +0 -36
  279. package/src/icons/components/SettingsIcon.tsx +0 -37
  280. package/src/icons/components/animated/LoadingIcon.tsx +0 -27
  281. package/src/icons/components/animated/PlayPauseIcon.tsx +0 -42
  282. package/src/icons/components/media/PauseIcon.tsx +0 -38
  283. package/src/icons/components/media/PlayIcon.tsx +0 -37
  284. package/src/icons/components/volume/VolumeIcon.tsx +0 -38
  285. package/src/icons/components/volume/VolumeOffIcon.tsx +0 -38
  286. package/src/icons/index.ts +0 -56
  287. package/src/icons/provider.tsx +0 -58
  288. package/src/icons/types.ts +0 -60
  289. package/src/index-enhanced.ts +0 -35
  290. package/src/index-legacy.ts +0 -324
  291. package/src/index.css +0 -102
  292. package/src/lib/__tests__/async-utils.test.ts +0 -291
  293. package/src/lib/async-utils.ts +0 -194
  294. package/src/lib/deprecation.ts +0 -51
  295. package/src/lib/format-time.ts +0 -37
  296. package/src/lib/index.ts +0 -4
  297. package/src/lib/utils.ts +0 -6
  298. package/src/styles/globals.css +0 -462
  299. package/src/styles/minimal-player.css +0 -621
  300. package/src/styles/pixel-art.css +0 -41
  301. package/src/styles/videojs.css +0 -100
  302. package/src/types/events.ts +0 -47
  303. package/src/types/formats.ts +0 -79
  304. package/src/types/index.ts +0 -203
  305. package/src/types/videojs-plugins.d.ts +0 -14
@@ -1,462 +0,0 @@
1
- "use client"
2
-
3
- import type { MediaState } from "./media-context"
4
-
5
- // Storage keys
6
- export const STORAGE_KEYS = {
7
- USER_PREFERENCES: "baroi-player-preferences",
8
- SESSION_STATE: "baroi-player-session",
9
- PLAYBACK_HISTORY: "baroi-player-history",
10
- CACHE_TIMESTAMP: "baroi-player-cache-ts"
11
- } as const
12
-
13
- // User preferences that should be persisted long-term
14
- export interface UserPreferences {
15
- volume: number
16
- isMuted: boolean
17
- playbackRate: number
18
- subtitlesShowing: boolean
19
- selectedSubtitleTrack: string | null
20
- preferredRendition: string | null
21
- autoplay: boolean
22
- keyboardShortcuts: boolean
23
- }
24
-
25
- // Session state that should be persisted for the session
26
- export interface SessionState {
27
- currentTime: number
28
- mediaId?: string
29
- src?: string
30
- playbackPosition: Record<string, number> // mediaId -> position
31
- }
32
-
33
- // Playback history item
34
- export interface PlaybackHistoryItem {
35
- mediaId: string
36
- src: string
37
- title?: string
38
- currentTime: number
39
- duration: number
40
- timestamp: number
41
- completed: boolean
42
- }
43
-
44
- // Persistence configuration
45
- export interface PersistenceConfig {
46
- // Storage options
47
- userPreferences: boolean
48
- sessionState: boolean
49
- playbackHistory: boolean
50
-
51
- // Limits
52
- maxHistoryItems: number
53
- maxCacheAge: number // milliseconds
54
-
55
- // Debouncing
56
- debounceMs: number
57
-
58
- // Custom storage adapter
59
- storage?: StorageAdapter
60
- }
61
-
62
- // Storage adapter interface for custom storage implementations
63
- export interface StorageAdapter {
64
- getItem(key: string): Promise<string | null>
65
- setItem(key: string, value: string): Promise<void>
66
- removeItem(key: string): Promise<void>
67
- clear(): Promise<void>
68
- }
69
-
70
- // Default localStorage adapter
71
- class LocalStorageAdapter implements StorageAdapter {
72
- async getItem(key: string): Promise<string | null> {
73
- if (typeof window === "undefined") return null
74
- try {
75
- return localStorage.getItem(key)
76
- } catch (error) {
77
- console.warn("Failed to read from localStorage:", error)
78
- return null
79
- }
80
- }
81
-
82
- async setItem(key: string, value: string): Promise<void> {
83
- if (typeof window === "undefined") return
84
- try {
85
- localStorage.setItem(key, value)
86
- } catch (error) {
87
- console.warn("Failed to write to localStorage:", error)
88
- }
89
- }
90
-
91
- async removeItem(key: string): Promise<void> {
92
- if (typeof window === "undefined") return
93
- try {
94
- localStorage.removeItem(key)
95
- } catch (error) {
96
- console.warn("Failed to remove from localStorage:", error)
97
- }
98
- }
99
-
100
- async clear(): Promise<void> {
101
- if (typeof window === "undefined") return
102
- try {
103
- // Only clear baroi-player keys
104
- Object.values(STORAGE_KEYS).forEach((key) => {
105
- localStorage.removeItem(key)
106
- })
107
- } catch (error) {
108
- console.warn("Failed to clear localStorage:", error)
109
- }
110
- }
111
- }
112
-
113
- // Default persistence configuration
114
- const DEFAULT_CONFIG: PersistenceConfig = {
115
- userPreferences: true,
116
- sessionState: true,
117
- playbackHistory: true,
118
- maxHistoryItems: 50,
119
- maxCacheAge: 7 * 24 * 60 * 60 * 1000, // 7 days
120
- debounceMs: 1000,
121
- storage: new LocalStorageAdapter()
122
- }
123
-
124
- // Persistence manager class
125
- export class MediaPersistenceManager {
126
- private config: PersistenceConfig
127
- private storage: StorageAdapter
128
- private debounceTimeouts: Map<string, NodeJS.Timeout> = new Map()
129
-
130
- constructor(config: Partial<PersistenceConfig> = {}) {
131
- this.config = { ...DEFAULT_CONFIG, ...config }
132
- this.storage = this.config.storage!
133
- }
134
-
135
- // User preferences methods
136
- async getUserPreferences(): Promise<UserPreferences | null> {
137
- if (!this.config.userPreferences) return null
138
-
139
- try {
140
- const data = await this.storage.getItem(STORAGE_KEYS.USER_PREFERENCES)
141
- if (!data) return null
142
-
143
- const parsed = JSON.parse(data) as { preferences: UserPreferences; timestamp: number }
144
-
145
- // Validate cache age
146
- if (this.isCacheExpired(parsed.timestamp)) {
147
- await this.clearUserPreferences()
148
- return null
149
- }
150
-
151
- return parsed.preferences
152
- } catch (error) {
153
- console.warn("Failed to get user preferences:", error)
154
- return null
155
- }
156
- }
157
-
158
- async saveUserPreferences(preferences: Partial<UserPreferences>): Promise<void> {
159
- if (!this.config.userPreferences) return
160
-
161
- this.debounce(STORAGE_KEYS.USER_PREFERENCES, async () => {
162
- try {
163
- const existing = (await this.getUserPreferences()) || {}
164
- const updated = { ...existing, ...preferences }
165
-
166
- await this.storage.setItem(
167
- STORAGE_KEYS.USER_PREFERENCES,
168
- JSON.stringify({
169
- preferences: updated,
170
- timestamp: Date.now()
171
- })
172
- )
173
- } catch (error) {
174
- console.warn("Failed to save user preferences:", error)
175
- }
176
- })
177
- }
178
-
179
- async clearUserPreferences(): Promise<void> {
180
- try {
181
- await this.storage.removeItem(STORAGE_KEYS.USER_PREFERENCES)
182
- } catch (error) {
183
- console.warn("Failed to clear user preferences:", error)
184
- }
185
- }
186
-
187
- // Session state methods
188
- async getSessionState(): Promise<SessionState | null> {
189
- if (!this.config.sessionState) return null
190
-
191
- try {
192
- const data = await this.storage.getItem(STORAGE_KEYS.SESSION_STATE)
193
- if (!data) return null
194
-
195
- const parsed = JSON.parse(data) as { state: SessionState; timestamp: number }
196
- return parsed.state
197
- } catch (error) {
198
- console.warn("Failed to get session state:", error)
199
- return null
200
- }
201
- }
202
-
203
- async saveSessionState(state: Partial<SessionState>): Promise<void> {
204
- if (!this.config.sessionState) return
205
-
206
- this.debounce(STORAGE_KEYS.SESSION_STATE, async () => {
207
- try {
208
- const existing = (await this.getSessionState()) || {
209
- currentTime: 0,
210
- playbackPosition: {}
211
- }
212
- const updated = { ...existing, ...state }
213
-
214
- await this.storage.setItem(
215
- STORAGE_KEYS.SESSION_STATE,
216
- JSON.stringify({
217
- state: updated,
218
- timestamp: Date.now()
219
- })
220
- )
221
- } catch (error) {
222
- console.warn("Failed to save session state:", error)
223
- }
224
- })
225
- }
226
-
227
- async clearSessionState(): Promise<void> {
228
- try {
229
- await this.storage.removeItem(STORAGE_KEYS.SESSION_STATE)
230
- } catch (error) {
231
- console.warn("Failed to clear session state:", error)
232
- }
233
- }
234
-
235
- // Playback history methods
236
- async getPlaybackHistory(): Promise<PlaybackHistoryItem[]> {
237
- if (!this.config.playbackHistory) return []
238
-
239
- try {
240
- const data = await this.storage.getItem(STORAGE_KEYS.PLAYBACK_HISTORY)
241
- if (!data) return []
242
-
243
- const parsed = JSON.parse(data) as { history: PlaybackHistoryItem[]; timestamp: number }
244
-
245
- // Validate cache age
246
- if (this.isCacheExpired(parsed.timestamp)) {
247
- await this.clearPlaybackHistory()
248
- return []
249
- }
250
-
251
- return parsed.history || []
252
- } catch (error) {
253
- console.warn("Failed to get playback history:", error)
254
- return []
255
- }
256
- }
257
-
258
- async addToPlaybackHistory(item: Omit<PlaybackHistoryItem, "timestamp">): Promise<void> {
259
- if (!this.config.playbackHistory) return
260
-
261
- try {
262
- const history = await this.getPlaybackHistory()
263
- const newItem: PlaybackHistoryItem = {
264
- ...item,
265
- timestamp: Date.now()
266
- }
267
-
268
- // Remove existing entry for the same media
269
- const filteredHistory = history.filter((h) => h.mediaId !== item.mediaId)
270
-
271
- // Add new item at the beginning
272
- const updatedHistory = [newItem, ...filteredHistory].slice(0, this.config.maxHistoryItems)
273
-
274
- await this.storage.setItem(
275
- STORAGE_KEYS.PLAYBACK_HISTORY,
276
- JSON.stringify({
277
- history: updatedHistory,
278
- timestamp: Date.now()
279
- })
280
- )
281
- } catch (error) {
282
- console.warn("Failed to add to playback history:", error)
283
- }
284
- }
285
-
286
- async clearPlaybackHistory(): Promise<void> {
287
- try {
288
- await this.storage.removeItem(STORAGE_KEYS.PLAYBACK_HISTORY)
289
- } catch (error) {
290
- console.warn("Failed to clear playback history:", error)
291
- }
292
- }
293
-
294
- // Utility methods
295
- async savePlaybackPosition(mediaId: string, position: number): Promise<void> {
296
- const session = await this.getSessionState()
297
- const playbackPosition = session?.playbackPosition || {}
298
-
299
- await this.saveSessionState({
300
- playbackPosition: {
301
- ...playbackPosition,
302
- [mediaId]: position
303
- }
304
- })
305
- }
306
-
307
- async getPlaybackPosition(mediaId: string): Promise<number> {
308
- const session = await this.getSessionState()
309
- return session?.playbackPosition?.[mediaId] || 0
310
- }
311
-
312
- // Extract preferences from MediaState
313
- extractUserPreferences(state: MediaState): UserPreferences {
314
- return {
315
- volume: state.volume,
316
- isMuted: state.isMuted,
317
- playbackRate: state.playbackRate,
318
- subtitlesShowing: state.subtitlesShowing,
319
- selectedSubtitleTrack: state.selectedSubtitleTrack?.id || null,
320
- preferredRendition: state.selectedRendition,
321
- autoplay: false, // This would come from config
322
- keyboardShortcuts: true // This would come from config
323
- }
324
- }
325
-
326
- // Extract session state from MediaState
327
- extractSessionState(state: MediaState, mediaId?: string): SessionState {
328
- return {
329
- currentTime: state.currentTime,
330
- mediaId,
331
- playbackPosition: {}
332
- }
333
- }
334
-
335
- // Clear all persisted data
336
- async clearAll(): Promise<void> {
337
- await this.storage.clear()
338
- this.debounceTimeouts.clear()
339
- }
340
-
341
- // Private helper methods
342
- private isCacheExpired(timestamp?: number): boolean {
343
- if (!timestamp) return true
344
- return Date.now() - timestamp > this.config.maxCacheAge
345
- }
346
-
347
- private debounce(key: string, fn: () => Promise<void>): void {
348
- const existingTimeout = this.debounceTimeouts.get(key)
349
- if (existingTimeout) {
350
- clearTimeout(existingTimeout)
351
- }
352
-
353
- const timeout = setTimeout(async () => {
354
- await fn()
355
- this.debounceTimeouts.delete(key)
356
- }, this.config.debounceMs)
357
-
358
- this.debounceTimeouts.set(key, timeout)
359
- }
360
- }
361
-
362
- // Hook for using persistence in components
363
- export function useMediaPersistence(config?: Partial<PersistenceConfig>) {
364
- const [manager] = React.useState(() => new MediaPersistenceManager(config))
365
-
366
- React.useEffect(() => {
367
- return () => {
368
- // Clear any pending debounced operations
369
- manager.clearAll()
370
- }
371
- }, [manager])
372
-
373
- return manager
374
- }
375
-
376
- // React 19 integration for automatic persistence
377
- export function useAutoMediaPersistence(
378
- state: MediaState,
379
- mediaId?: string,
380
- config?: Partial<PersistenceConfig>
381
- ) {
382
- const manager = useMediaPersistence(config)
383
- const [isRehydrated, setIsRehydrated] = React.useState(false)
384
-
385
- // Rehydrate on mount
386
- React.useEffect(() => {
387
- let isMounted = true
388
-
389
- const rehydrate = async () => {
390
- try {
391
- const [preferences, session] = await Promise.all([
392
- manager.getUserPreferences(),
393
- manager.getSessionState()
394
- ])
395
-
396
- if (!isMounted) return
397
-
398
- // Return the rehydrated state for the store to apply
399
- const rehydratedState: Partial<MediaState> = {
400
- ...(preferences && {
401
- volume: preferences.volume,
402
- isMuted: preferences.isMuted,
403
- playbackRate: preferences.playbackRate,
404
- subtitlesShowing: preferences.subtitlesShowing
405
- }),
406
- ...(session &&
407
- mediaId === session.mediaId && {
408
- currentTime: session.currentTime
409
- })
410
- }
411
-
412
- // Apply rehydrated state via callback if provided
413
- if (Object.keys(rehydratedState).length > 0) {
414
- // This would be handled by the store
415
- console.log("Rehydrated state:", rehydratedState)
416
- }
417
-
418
- setIsRehydrated(true)
419
- } catch (error) {
420
- console.warn("Failed to rehydrate state:", error)
421
- setIsRehydrated(true)
422
- }
423
- }
424
-
425
- rehydrate()
426
-
427
- return () => {
428
- isMounted = false
429
- }
430
- }, [manager, mediaId])
431
-
432
- // Auto-persist changes
433
- React.useEffect(() => {
434
- if (!isRehydrated) return
435
-
436
- // Save user preferences
437
- const preferences = manager.extractUserPreferences(state)
438
- manager.saveUserPreferences(preferences)
439
-
440
- // Save session state
441
- if (mediaId) {
442
- const session = manager.extractSessionState(state, mediaId)
443
- manager.saveSessionState(session)
444
-
445
- // Save playback position
446
- if (state.currentTime > 0 && state.duration > 0) {
447
- manager.savePlaybackPosition(mediaId, state.currentTime)
448
- }
449
- }
450
- }, [manager, state, mediaId, isRehydrated])
451
-
452
- return {
453
- manager,
454
- isRehydrated
455
- }
456
- }
457
-
458
- // Export default storage adapter
459
- export const defaultStorageAdapter = new LocalStorageAdapter()
460
-
461
- // Import React for hooks
462
- import React from "react"