@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.
- package/README.md +90 -71
- package/dist/components/icons/index.d.ts +36 -0
- package/dist/components/icons/index.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts +4 -0
- package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/AudioIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/AudioIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/BackwardIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/BackwardIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/CameraIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/CameraIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/CheckIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/CheckIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts +4 -0
- package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/ForwardIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/ForwardIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/LoadingIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/LoadingIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/PauseIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/PauseIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/PlayIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/PlayIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/QualityIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/QualityIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/SettingsIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/SettingsIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/SliderIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/SliderIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/SubtitleIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/SubtitleIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/UnPiPIcon.d.ts +4 -0
- package/dist/components/icons/svg-icons/UnPiPIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts.map +1 -0
- package/dist/components/variants/gradient/gradient-audio.d.ts +13 -0
- package/dist/components/variants/gradient/gradient-audio.d.ts.map +1 -0
- package/dist/components/variants/gradient/gradient-controls.d.ts +4 -0
- package/dist/components/variants/gradient/gradient-controls.d.ts.map +1 -0
- package/dist/components/variants/gradient/gradient-glyphs.d.ts +30 -0
- package/dist/components/variants/gradient/gradient-glyphs.d.ts.map +1 -0
- package/dist/components/variants/gradient/gradient-video.d.ts +16 -0
- package/dist/components/variants/gradient/gradient-video.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +750 -5640
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +3 -0
- package/package.json +110 -114
- package/src/components/variants/gradient/gradient-audio.tsx +47 -0
- package/src/components/variants/gradient/gradient-controls.tsx +254 -0
- package/src/components/variants/gradient/gradient-glyphs.test.tsx +69 -0
- package/src/components/variants/gradient/gradient-glyphs.tsx +129 -0
- package/src/components/variants/gradient/gradient-skin.css +211 -0
- package/src/components/variants/gradient/gradient-video.tsx +70 -0
- package/src/index.ts +5 -198
- package/src/test/accessibility-utils.ts +0 -59
- package/dist/context/media.js +0 -1
- package/dist/context/media.mjs +0 -3
- package/dist/context/store.js +0 -1
- package/dist/context/store.mjs +0 -3
- package/dist/context-Bzd5QCKM.cjs +0 -7
- package/dist/context-Bzd5QCKM.cjs.map +0 -1
- package/dist/context-DD_SH4tT.js +0 -1053
- package/dist/context-DD_SH4tT.js.map +0 -1
- package/dist/core-events-BRnLMB7s.cjs +0 -2
- package/dist/core-events-BRnLMB7s.cjs.map +0 -1
- package/dist/core-events-v_mKdj5p.js +0 -417
- package/dist/core-events-v_mKdj5p.js.map +0 -1
- package/dist/core-plugins-CMBv-yVh.cjs +0 -2
- package/dist/core-plugins-CMBv-yVh.cjs.map +0 -1
- package/dist/core-plugins-CqCxLkbd.js +0 -754
- package/dist/core-plugins-CqCxLkbd.js.map +0 -1
- package/dist/core.js +0 -15
- package/dist/core.js.map +0 -1
- package/dist/core.mjs +0 -960
- package/dist/core.mjs.map +0 -1
- package/dist/enhanced-components-BwjBqSA1.js +0 -2858
- package/dist/enhanced-components-BwjBqSA1.js.map +0 -1
- package/dist/enhanced-components-C-ka-XLp.cjs +0 -2
- package/dist/enhanced-components-C-ka-XLp.cjs.map +0 -1
- package/dist/hooks-B-IIWPJr.js +0 -1842
- package/dist/hooks-B-IIWPJr.js.map +0 -1
- package/dist/hooks-DcHzmBwA.cjs +0 -4
- package/dist/hooks-DcHzmBwA.cjs.map +0 -1
- package/dist/minimal-components-BYsMQde5.js +0 -1610
- package/dist/minimal-components-BYsMQde5.js.map +0 -1
- package/dist/minimal-components-CsxQbDp7.cjs +0 -2
- package/dist/minimal-components-CsxQbDp7.cjs.map +0 -1
- package/dist/minimal-components.css +0 -1
- package/dist/mona-loading.gif +0 -0
- package/dist/performance-monitor-DCSijLJg.js +0 -312
- package/dist/performance-monitor-DCSijLJg.js.map +0 -1
- package/dist/performance-monitor-wNFKmqMr.cjs +0 -2
- package/dist/performance-monitor-wNFKmqMr.cjs.map +0 -1
- package/dist/rolldown-runtime-BmowowmI.js +0 -14
- package/dist/rolldown-runtime-mLOUI7ql.cjs +0 -1
- package/dist/utils-D2gQ7c2R.js +0 -64
- package/dist/utils-D2gQ7c2R.js.map +0 -1
- package/dist/utils-DJaAwiZ9.cjs +0 -2
- package/dist/utils-DJaAwiZ9.cjs.map +0 -1
- package/dist/utils.js +0 -1
- package/dist/utils.mjs +0 -3
- package/src/adapters/videojs-adapter.tsx +0 -470
- package/src/assets/mona-loading.gif +0 -0
- package/src/components/AnimateLoading.tsx +0 -111
- package/src/components/LoadingState.tsx +0 -239
- package/src/components/__tests__/media-player-accessibility.test.tsx +0 -510
- package/src/components/__tests__/media-player-react19.test.tsx +0 -457
- package/src/components/accessibility/keyboard-help-overlay.tsx +0 -207
- package/src/components/audio-player.tsx +0 -85
- package/src/components/basic/index.ts +0 -37
- package/src/components/enhanced/advanced-features.tsx +0 -311
- package/src/components/enhanced/debug-panel.tsx +0 -448
- package/src/components/enhanced/enhanced-controls.tsx +0 -597
- package/src/components/enhanced/enhanced-media-player.tsx +0 -566
- package/src/components/enhanced/error-handling.tsx +0 -338
- package/src/components/enhanced/index.ts +0 -39
- package/src/components/enhanced/media-player-enhanced.tsx +0 -383
- package/src/components/examples/basic-video-player.tsx +0 -50
- package/src/components/examples/custom-controls-example.tsx +0 -63
- package/src/components/examples/enhanced-controls-example.tsx +0 -100
- package/src/components/examples/enhanced-media-player-example.tsx +0 -302
- package/src/components/examples/loading-states-demo.tsx +0 -141
- package/src/components/examples/react-19-demo.tsx +0 -349
- package/src/components/examples/volume-orientation-demo.tsx +0 -105
- package/src/components/icon-demo.tsx +0 -196
- package/src/components/legacy.tsx +0 -87
- package/src/components/media-metadata-display.tsx +0 -99
- package/src/components/media-player-audio.tsx +0 -39
- package/src/components/media-player-controls.tsx +0 -223
- package/src/components/media-player-error.tsx +0 -163
- package/src/components/media-player-fullscreen.tsx +0 -109
- package/src/components/media-player-hls.tsx +0 -111
- package/src/components/media-player-loading.tsx +0 -76
- package/src/components/media-player-play.tsx +0 -75
- package/src/components/media-player-root.tsx +0 -338
- package/src/components/media-player-seek.tsx +0 -168
- package/src/components/media-player-time.tsx +0 -99
- package/src/components/media-player-tooltip.tsx +0 -58
- package/src/components/media-player-video.tsx +0 -54
- package/src/components/media-player-volume.tsx +0 -155
- package/src/components/media-player.tsx +0 -292
- package/src/components/media-suspense.tsx +0 -344
- package/src/components/player-settings-form.tsx +0 -158
- package/src/components/react-player-wrapper.tsx +0 -651
- package/src/components/simple-video-player.tsx +0 -62
- package/src/components/ui/blur-poster.tsx +0 -96
- package/src/components/ui/empty-state.tsx +0 -91
- package/src/components/ui/enhanced-seek-bar.tsx +0 -254
- package/src/components/ui/error-state.tsx +0 -124
- package/src/components/ui/fullscreen-button.tsx +0 -81
- package/src/components/ui/loading-skeleton.tsx +0 -107
- package/src/components/ui/media-resource-preloader.tsx +0 -458
- package/src/components/ui/offline-message.tsx +0 -98
- package/src/components/ui/play-button.tsx +0 -99
- package/src/components/ui/seek-bar.tsx +0 -191
- package/src/components/ui/time-display.tsx +0 -61
- package/src/components/ui/volume-control.tsx +0 -190
- package/src/components/unified/base-media-player.tsx +0 -252
- package/src/components/unified/media-player.tsx +0 -75
- package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +0 -587
- package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +0 -573
- package/src/components/variants/minimal/MinimalControls.tsx +0 -124
- package/src/components/variants/minimal/MinimalLoading.tsx +0 -28
- package/src/components/variants/minimal/MinimalMediaPlayer.tsx +0 -318
- package/src/components/variants/minimal/MinimalOverlay.tsx +0 -58
- package/src/components/variants/minimal/MinimalPlayButton.tsx +0 -56
- package/src/components/variants/minimal/MinimalSeekBar.tsx +0 -140
- package/src/components/variants/minimal/MinimalVolumeControl.tsx +0 -75
- package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +0 -206
- package/src/components/variants/minimal/components/CenterPlayButton.tsx +0 -22
- package/src/components/variants/minimal/components/ControlBar.tsx +0 -142
- package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +0 -412
- package/src/components/variants/minimal/components/PlaybackControls.tsx +0 -46
- package/src/components/variants/minimal/components/RightControls.tsx +0 -164
- package/src/components/variants/minimal/components/SeekBar.tsx +0 -127
- package/src/components/variants/minimal/components/SettingsDropdown.tsx +0 -68
- package/src/components/variants/minimal/components/SubtitleDisplay.tsx +0 -21
- package/src/components/variants/minimal/components/TimeDisplay.tsx +0 -15
- package/src/components/variants/minimal/components/VideoElement.tsx +0 -35
- package/src/components/variants/minimal/components/VolumeControl.tsx +0 -220
- package/src/components/variants/minimal/index.ts +0 -23
- package/src/components/video-player.tsx +0 -100
- package/src/context/__tests__/media-store.test.ts +0 -509
- package/src/context/error-handling.ts +0 -398
- package/src/context/media-context.tsx +0 -254
- package/src/context/media-provider.tsx +0 -264
- package/src/context/media-store.ts +0 -387
- package/src/context/persistence.ts +0 -462
- package/src/core/events/event-system.ts +0 -448
- package/src/core/events/hooks.ts +0 -325
- package/src/core/events/index.ts +0 -22
- package/src/core/events/middleware.ts +0 -286
- package/src/core/index.ts +0 -22
- package/src/core/optimization/bundle-optimizer.tsx +0 -312
- package/src/core/performance/cicd.ts +0 -98
- package/src/core/performance/index.ts +0 -38
- package/src/core/performance/media-loading-optimizer.ts +0 -545
- package/src/core/performance/performance-budgets.ts +0 -437
- package/src/core/performance/performance-monitor.tsx +0 -488
- package/src/core/performance/performance-testing.ts +0 -461
- package/src/core/plugins/__tests__/registry.test.ts +0 -595
- package/src/core/plugins/base-plugin.ts +0 -225
- package/src/core/plugins/enhanced-plugin-system.ts +0 -435
- package/src/core/plugins/examples/analytics-plugin.ts +0 -241
- package/src/core/plugins/index.ts +0 -39
- package/src/core/plugins/registry.ts +0 -546
- package/src/core/plugins/types.ts +0 -169
- package/src/core/plugins/utils.ts +0 -317
- package/src/core/progressive-loading.tsx +0 -331
- package/src/core/providers/enhanced-hls-provider.ts +0 -307
- package/src/core/providers/lazy-provider.tsx +0 -14
- package/src/core/providers/service-provider.tsx +0 -164
- package/src/core/utils.tsx +0 -34
- package/src/features/media-session/media-session-manager.ts +0 -411
- package/src/features/picture-in-picture/pip-manager.ts +0 -428
- package/src/features/playlist/playlist-manager.ts +0 -626
- package/src/features/subtitles/subtitle-manager.ts +0 -435
- package/src/features/subtitles/subtitle-parser.ts +0 -284
- package/src/features/thumbnails/thumbnail-generator.ts +0 -528
- package/src/hooks/__tests__/currentTime-fix.test.ts +0 -149
- package/src/hooks/__tests__/use-media-player.test.ts +0 -712
- package/src/hooks/__tests__/use-media-state.test.tsx +0 -316
- package/src/hooks/accessibility/index.ts +0 -27
- package/src/hooks/accessibility/use-accessibility-preferences.ts +0 -190
- package/src/hooks/accessibility/use-focus-management.ts +0 -183
- package/src/hooks/accessibility/use-keyboard-shortcuts.ts +0 -152
- package/src/hooks/accessibility/use-screen-reader.ts +0 -212
- package/src/hooks/core/index.ts +0 -47
- package/src/hooks/legacy.ts +0 -21
- package/src/hooks/use-buffer-health.ts +0 -218
- package/src/hooks/use-enhanced-media-player.ts +0 -575
- package/src/hooks/use-focus-trap.tsx +0 -162
- package/src/hooks/use-intelligent-preloading.ts +0 -387
- package/src/hooks/use-keyboard-controls.ts +0 -115
- package/src/hooks/use-keyboard-shortcuts.ts +0 -255
- package/src/hooks/use-media-actions.ts +0 -184
- package/src/hooks/use-media-metadata.ts +0 -91
- package/src/hooks/use-media-optimistic.ts +0 -264
- package/src/hooks/use-media-player.ts +0 -343
- package/src/hooks/use-media-state.ts +0 -194
- package/src/hooks/use-memory-optimization.ts +0 -360
- package/src/hooks/use-network-status.ts +0 -124
- package/src/hooks/use-optimistic-controls.ts +0 -95
- package/src/hooks/use-optimized-media.ts +0 -283
- package/src/hooks/use-smart-preload.ts +0 -229
- package/src/hooks/use-touch-gestures.ts +0 -461
- package/src/hooks/useEnhancedSubtitles.ts +0 -258
- package/src/hooks/useKeyboardShortcuts.ts +0 -106
- package/src/hooks/useMediaControls.ts +0 -52
- package/src/hooks/useScreenshot.ts +0 -77
- package/src/hooks/useSubtitles.ts +0 -91
- package/src/hooks/useVideoPlayer.ts +0 -278
- package/src/icons/components/FullscreenIcon.tsx +0 -36
- package/src/icons/components/SettingsIcon.tsx +0 -37
- package/src/icons/components/animated/LoadingIcon.tsx +0 -27
- package/src/icons/components/animated/PlayPauseIcon.tsx +0 -42
- package/src/icons/components/media/PauseIcon.tsx +0 -38
- package/src/icons/components/media/PlayIcon.tsx +0 -37
- package/src/icons/components/volume/VolumeIcon.tsx +0 -38
- package/src/icons/components/volume/VolumeOffIcon.tsx +0 -38
- package/src/icons/index.ts +0 -56
- package/src/icons/provider.tsx +0 -58
- package/src/icons/types.ts +0 -60
- package/src/index-enhanced.ts +0 -35
- package/src/index-legacy.ts +0 -324
- package/src/index.css +0 -102
- package/src/lib/__tests__/async-utils.test.ts +0 -291
- package/src/lib/async-utils.ts +0 -194
- package/src/lib/deprecation.ts +0 -51
- package/src/lib/format-time.ts +0 -37
- package/src/lib/index.ts +0 -4
- package/src/lib/utils.ts +0 -6
- package/src/styles/globals.css +0 -462
- package/src/styles/minimal-player.css +0 -621
- package/src/styles/pixel-art.css +0 -41
- package/src/styles/videojs.css +0 -100
- package/src/types/assets.d.ts +0 -29
- package/src/types/events.ts +0 -47
- package/src/types/formats.ts +0 -79
- package/src/types/index.ts +0 -203
- 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"
|