@therealtinhtute/baroiplayer 1.2.0 → 1.2.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 (97) hide show
  1. package/README.md +1 -2
  2. package/dist/context/media.js +1 -2
  3. package/dist/context/media.mjs +3 -15
  4. package/dist/context/store.js +1 -2
  5. package/dist/context/store.mjs +3 -5
  6. package/dist/context-Bzd5QCKM.cjs +7 -0
  7. package/dist/context-Bzd5QCKM.cjs.map +1 -0
  8. package/dist/context-DD_SH4tT.js +1053 -0
  9. package/dist/context-DD_SH4tT.js.map +1 -0
  10. package/dist/core-events-BRnLMB7s.cjs +2 -0
  11. package/dist/core-events-BRnLMB7s.cjs.map +1 -0
  12. package/dist/core-events-v_mKdj5p.js +417 -0
  13. package/dist/core-events-v_mKdj5p.js.map +1 -0
  14. package/dist/core-plugins-CMBv-yVh.cjs +2 -0
  15. package/dist/core-plugins-CMBv-yVh.cjs.map +1 -0
  16. package/dist/core-plugins-CqCxLkbd.js +754 -0
  17. package/dist/core-plugins-CqCxLkbd.js.map +1 -0
  18. package/dist/core.js +7 -29
  19. package/dist/core.js.map +1 -1
  20. package/dist/core.mjs +947 -1220
  21. package/dist/core.mjs.map +1 -1
  22. package/dist/enhanced-components-BwjBqSA1.js +2858 -0
  23. package/dist/enhanced-components-BwjBqSA1.js.map +1 -0
  24. package/dist/enhanced-components-C-ka-XLp.cjs +2 -0
  25. package/dist/enhanced-components-C-ka-XLp.cjs.map +1 -0
  26. package/dist/hooks-B-IIWPJr.js +1842 -0
  27. package/dist/hooks-B-IIWPJr.js.map +1 -0
  28. package/dist/hooks-DcHzmBwA.cjs +4 -0
  29. package/dist/hooks-DcHzmBwA.cjs.map +1 -0
  30. package/dist/index.js +27 -97
  31. package/dist/index.js.map +1 -1
  32. package/dist/index.mjs +5613 -6208
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/minimal-components-BYsMQde5.js +1610 -0
  35. package/dist/minimal-components-BYsMQde5.js.map +1 -0
  36. package/dist/minimal-components-CsxQbDp7.cjs +2 -0
  37. package/dist/minimal-components-CsxQbDp7.cjs.map +1 -0
  38. package/dist/performance-monitor-DCSijLJg.js +312 -0
  39. package/dist/performance-monitor-DCSijLJg.js.map +1 -0
  40. package/dist/performance-monitor-wNFKmqMr.cjs +2 -0
  41. package/dist/performance-monitor-wNFKmqMr.cjs.map +1 -0
  42. package/dist/rolldown-runtime-BmowowmI.js +14 -0
  43. package/dist/rolldown-runtime-mLOUI7ql.cjs +1 -0
  44. package/dist/utils-D2gQ7c2R.js +64 -0
  45. package/dist/utils-D2gQ7c2R.js.map +1 -0
  46. package/dist/utils-DJaAwiZ9.cjs +2 -0
  47. package/dist/utils-DJaAwiZ9.cjs.map +1 -0
  48. package/dist/utils.js +1 -2
  49. package/dist/utils.mjs +3 -11
  50. package/package.json +28 -22
  51. package/src/components/AnimateLoading.tsx +14 -10
  52. package/src/components/examples/loading-states-demo.tsx +1 -2
  53. package/src/components/examples/react-19-demo.tsx +6 -10
  54. package/src/components/examples/volume-orientation-demo.tsx +1 -2
  55. package/src/components/ui/blur-poster.tsx +18 -15
  56. package/src/components/variants/minimal/components/VideoElement.tsx +3 -1
  57. package/src/core/performance/media-loading-optimizer.ts +2 -1
  58. package/src/hooks/useScreenshot.ts +60 -44
  59. package/src/types/assets.d.ts +29 -0
  60. package/dist/context/media.js.map +0 -1
  61. package/dist/context/media.mjs.map +0 -1
  62. package/dist/context/store.js.map +0 -1
  63. package/dist/context/store.mjs.map +0 -1
  64. package/dist/context-BYwDoSRX.js +0 -1172
  65. package/dist/context-BYwDoSRX.js.map +0 -1
  66. package/dist/context-eNS62_ac.cjs +0 -23
  67. package/dist/context-eNS62_ac.cjs.map +0 -1
  68. package/dist/core-events-B1iM2F46.cjs +0 -2
  69. package/dist/core-events-B1iM2F46.cjs.map +0 -1
  70. package/dist/core-events-DunPHKRE.js +0 -484
  71. package/dist/core-events-DunPHKRE.js.map +0 -1
  72. package/dist/core-plugins-By-4-kGs.cjs +0 -2
  73. package/dist/core-plugins-By-4-kGs.cjs.map +0 -1
  74. package/dist/core-plugins-DSBWcTuX.js +0 -821
  75. package/dist/core-plugins-DSBWcTuX.js.map +0 -1
  76. package/dist/enhanced-components-B_l3cist.js +0 -1142
  77. package/dist/enhanced-components-B_l3cist.js.map +0 -1
  78. package/dist/enhanced-components-BspFs9OO.cjs +0 -2
  79. package/dist/enhanced-components-BspFs9OO.cjs.map +0 -1
  80. package/dist/hooks-BXwI8QG6.cjs +0 -4
  81. package/dist/hooks-BXwI8QG6.cjs.map +0 -1
  82. package/dist/hooks-Bpi-jDiO.js +0 -1816
  83. package/dist/hooks-Bpi-jDiO.js.map +0 -1
  84. package/dist/minimal-components-C4z900Ro.js +0 -1926
  85. package/dist/minimal-components-C4z900Ro.js.map +0 -1
  86. package/dist/minimal-components-v4qBp6jv.cjs +0 -2
  87. package/dist/minimal-components-v4qBp6jv.cjs.map +0 -1
  88. package/dist/performance-monitor-C5k6FDXw.js +0 -301
  89. package/dist/performance-monitor-C5k6FDXw.js.map +0 -1
  90. package/dist/performance-monitor-lJmuUjQQ.cjs +0 -2
  91. package/dist/performance-monitor-lJmuUjQQ.cjs.map +0 -1
  92. package/dist/utils-CFOue_9K.cjs +0 -9
  93. package/dist/utils-CFOue_9K.cjs.map +0 -1
  94. package/dist/utils-Dzpl2ArK.js +0 -2844
  95. package/dist/utils-Dzpl2ArK.js.map +0 -1
  96. package/dist/utils.js.map +0 -1
  97. package/dist/utils.mjs.map +0 -1
@@ -1,1816 +0,0 @@
1
- import * as X from "react";
2
- import j, { useOptimistic as ce, useRef as H, useTransition as de, useEffect as G, useCallback as S, useMemo as ue, useState as W } from "react";
3
- import { M as _, c as we, b as Q } from "./context-BYwDoSRX.js";
4
- import { s as Te } from "./utils-Dzpl2ArK.js";
5
- function B(e, t) {
6
- return ((n, s = !1) => {
7
- const d = {
8
- type: e,
9
- detail: n,
10
- optimistic: s,
11
- timestamp: Date.now()
12
- };
13
- return s ? t.dispatchOptimistic(d) : (t.dispatch(d), Promise.resolve());
14
- });
15
- }
16
- function ye(e) {
17
- const [t, n] = j.useState(e.getActionState());
18
- return j.useEffect(() => e.subscribe(() => {
19
- const d = e.getActionState();
20
- n(
21
- (u) => JSON.stringify(u) !== JSON.stringify(d) ? d : u
22
- );
23
- }), [e]), t;
24
- }
25
- function be(e) {
26
- const t = j.useMemo(
27
- () => ({
28
- // Playback actions
29
- play: B(_.PLAY, e),
30
- pause: B(_.PAUSE, e),
31
- seek: B(_.SEEK, e),
32
- // Volume actions
33
- setVolume: B(_.SET_VOLUME, e),
34
- mute: B(_.MUTE, e),
35
- unmute: B(_.UNMUTE, e),
36
- toggleMute: B(_.TOGGLE_MUTE, e),
37
- // Media state actions
38
- setDuration: B(_.SET_DURATION, e),
39
- setCurrentTime: B(_.SET_CURRENT_TIME, e),
40
- setBuffered: B(_.SET_BUFFERED, e),
41
- setLoading: B(_.SET_LOADING, e),
42
- setError: B(_.SET_ERROR, e),
43
- // Display actions
44
- enterFullscreen: B(_.ENTER_FULLSCREEN, e),
45
- exitFullscreen: B(_.EXIT_FULLSCREEN, e),
46
- enterPiP: B(_.ENTER_PIP, e),
47
- exitPiP: B(_.EXIT_PIP, e),
48
- // Advanced actions
49
- setPlaybackRate: B(_.SET_PLAYBACK_RATE, e),
50
- setSubtitleTrack: B(_.SET_SUBTITLE_TRACK, e),
51
- setRendition: B(_.SET_RENDITION, e),
52
- toggleSubtitles: B(_.TOGGLE_SUBTITLES, e),
53
- // Preview actions
54
- previewTime: B(_.PREVIEW_TIME, e),
55
- clearPreview: B(_.CLEAR_PREVIEW, e)
56
- }),
57
- [e]
58
- ), n = ye(e), s = j.useMemo(
59
- () => ({
60
- // These actions benefit from immediate UI feedback
61
- togglePlayPause: async (u) => {
62
- u ? await t.pause(!0) : await t.play(!0);
63
- },
64
- seekWithPreview: async (u) => {
65
- await t.previewTime(u, !0), await t.seek(u, !0);
66
- },
67
- adjustVolume: async (u, a) => {
68
- const l = Math.max(0, Math.min(1, a + u));
69
- await t.setVolume(l, !0);
70
- },
71
- toggleFullscreenOptimistic: async (u) => {
72
- u ? await t.exitFullscreen(!0) : await t.enterFullscreen(!0);
73
- }
74
- }),
75
- [t]
76
- ), d = j.useCallback(async () => {
77
- const { lastAction: u } = n;
78
- u && n.error && await e.dispatchOptimistic({
79
- ...u,
80
- retryCount: (u.retryCount || 0) + 1
81
- });
82
- }, [e, n]);
83
- return {
84
- ...t,
85
- ...s,
86
- actionState: n,
87
- retryLastAction: d,
88
- isLoading: n.pending,
89
- hasError: !!n.error,
90
- errorMessage: n.error,
91
- retryCount: n.retryCount
92
- };
93
- }
94
- function Ee(e, t) {
95
- if (!t.optimistic) return e;
96
- switch (t.type) {
97
- case "PLAY":
98
- return { ...e, isPlaying: !0, error: null };
99
- case "PAUSE":
100
- return { ...e, isPlaying: !1 };
101
- case "SEEK":
102
- return { ...e, currentTime: t.detail };
103
- case "SET_VOLUME":
104
- return { ...e, volume: Math.max(0, Math.min(1, t.detail)) };
105
- case "MUTE":
106
- return { ...e, isMuted: !0 };
107
- case "UNMUTE":
108
- return { ...e, isMuted: !1 };
109
- case "TOGGLE_MUTE":
110
- return { ...e, isMuted: !e.isMuted };
111
- case "ENTER_FULLSCREEN":
112
- return { ...e, isFullscreen: !0 };
113
- case "EXIT_FULLSCREEN":
114
- return { ...e, isFullscreen: !1 };
115
- case "SET_PLAYBACK_RATE":
116
- return { ...e, playbackRate: t.detail };
117
- case "TOGGLE_SUBTITLES":
118
- return { ...e, subtitlesShowing: !e.subtitlesShowing };
119
- case "PREVIEW_TIME":
120
- return { ...e, previewTime: t.detail };
121
- case "CLEAR_PREVIEW":
122
- return {
123
- ...e,
124
- previewTime: null,
125
- previewImage: null,
126
- previewCoords: null
127
- };
128
- default:
129
- return e;
130
- }
131
- }
132
- function Se(e) {
133
- const t = j.useSyncExternalStore(e.subscribe, e.getState, e.getState), [n, s] = ce(t, Ee), d = j.useCallback(
134
- async (l) => {
135
- l.optimistic && s(l), await e.dispatchOptimistic(l);
136
- },
137
- [e, s]
138
- ), u = j.useMemo(
139
- () => ({
140
- // Play/Pause with immediate feedback
141
- togglePlayPause: async () => {
142
- const l = {
143
- type: n.isPlaying ? "PAUSE" : "PLAY",
144
- optimistic: !0,
145
- timestamp: Date.now()
146
- };
147
- await d(l);
148
- },
149
- // Volume control with immediate slider feedback
150
- setVolumeOptimistic: async (l) => {
151
- const b = {
152
- type: "SET_VOLUME",
153
- detail: Math.max(0, Math.min(1, l)),
154
- optimistic: !0,
155
- timestamp: Date.now()
156
- };
157
- await d(b);
158
- },
159
- // Seek with immediate scrub feedback
160
- seekOptimistic: async (l) => {
161
- const b = {
162
- type: "SEEK",
163
- detail: l,
164
- optimistic: !0,
165
- timestamp: Date.now()
166
- };
167
- await d(b);
168
- },
169
- // Mute toggle with immediate icon change
170
- toggleMuteOptimistic: async () => {
171
- const l = {
172
- type: "TOGGLE_MUTE",
173
- optimistic: !0,
174
- timestamp: Date.now()
175
- };
176
- await d(l);
177
- },
178
- // Fullscreen toggle with immediate layout change
179
- toggleFullscreenOptimistic: async () => {
180
- const l = {
181
- type: n.isFullscreen ? "EXIT_FULLSCREEN" : "ENTER_FULLSCREEN",
182
- optimistic: !0,
183
- timestamp: Date.now()
184
- };
185
- await d(l);
186
- },
187
- // Playback rate with immediate feedback
188
- setPlaybackRateOptimistic: async (l) => {
189
- const b = {
190
- type: "SET_PLAYBACK_RATE",
191
- detail: l,
192
- optimistic: !0,
193
- timestamp: Date.now()
194
- };
195
- await d(b);
196
- },
197
- // Subtitle toggle with immediate visibility change
198
- toggleSubtitlesOptimistic: async () => {
199
- const l = {
200
- type: "TOGGLE_SUBTITLES",
201
- optimistic: !0,
202
- timestamp: Date.now()
203
- };
204
- await d(l);
205
- }
206
- }),
207
- [n, d]
208
- ), a = j.useMemo(
209
- () => ({
210
- isPlaying: n.isPlaying,
211
- currentTime: n.currentTime,
212
- volume: n.volume,
213
- isMuted: n.isMuted,
214
- isFullscreen: n.isFullscreen,
215
- playbackRate: n.playbackRate,
216
- subtitlesShowing: n.subtitlesShowing,
217
- previewTime: n.previewTime,
218
- // Computed values
219
- progress: n.duration > 0 ? n.currentTime / n.duration : 0,
220
- formattedTime: me(n.currentTime),
221
- formattedDuration: me(n.duration),
222
- // State checks
223
- canPlay: !n.isLoading && !n.error,
224
- hasError: !!n.error,
225
- isBuffering: n.isLoading
226
- }),
227
- [n]
228
- );
229
- return {
230
- state: n,
231
- actualState: t,
232
- ...a,
233
- ...u,
234
- dispatchOptimistic: d
235
- };
236
- }
237
- function me(e) {
238
- if (!e || !isFinite(e)) return "0:00";
239
- const t = Math.floor(e / 60), n = Math.floor(e % 60), s = Math.floor(t / 60);
240
- return s > 0 ? `${s}:${String(t % 60).padStart(2, "0")}:${String(n).padStart(2, "0")}` : `${t}:${String(n).padStart(2, "0")}`;
241
- }
242
- function fe(e, t) {
243
- if (!Number.isFinite(t))
244
- return console.warn(`Attempted to set non-finite currentTime: ${t}`), !1;
245
- if (t < 0)
246
- return console.warn(`Attempted to set negative currentTime: ${t}`), !1;
247
- try {
248
- return e.currentTime = t, !0;
249
- } catch (n) {
250
- return console.error(`Failed to set currentTime to ${t}:`, n), !1;
251
- }
252
- }
253
- function Be(e) {
254
- const t = H(null), n = H(null), [s, d] = de(), [u, a] = de();
255
- j.useRef(0);
256
- const l = j.useRef(0), b = j.useRef(0);
257
- H(void 0);
258
- const k = H(0), M = we(), w = "getOptimisticState" in M, r = Q((y) => y.isPlaying), g = Q((y) => y.currentTime), m = Q((y) => y.duration), i = Q((y) => y.volume), h = Q((y) => y.isMuted), F = Q((y) => y.isLoading), f = Q((y) => y.isBuffering), o = Q((y) => y.error), v = Q((y) => y.buffered), p = Q((y) => y.isFullscreen), E = M, L = Se(E), T = be(E), [$, D] = j.useState({
259
- frameRate: 0,
260
- averageRenderTime: 0,
261
- droppedFrames: 0,
262
- bufferHealth: 0
263
- }), [I, C] = ce(
264
- i,
265
- (y, U) => Math.max(0, Math.min(1, U))
266
- );
267
- ce(
268
- g,
269
- (y, U) => Math.max(0, Math.min(m || 0, U))
270
- ), G(() => {
271
- const y = t.current;
272
- if (!y) return;
273
- const U = {
274
- volume: e.volume,
275
- muted: e.muted,
276
- autoplay: e.autoPlay,
277
- loop: e.loop,
278
- preload: e.preload,
279
- crossOrigin: e.crossOrigin
280
- };
281
- Object.entries(U).forEach(([z, Z]) => {
282
- Z !== void 0 && (y[z] = Z);
283
- }), y.setAttribute("preload", e.preloadStrategy === "eager" ? "auto" : "metadata"), e.bufferingStrategy === "aggressive" && y.setAttribute("buffered", "auto"), y instanceof HTMLVideoElement && (y.style.willChange = "transform", y.style.transform = "translateZ(0)");
284
- }, [
285
- e.volume,
286
- e.muted,
287
- e.autoPlay,
288
- e.loop,
289
- e.preload,
290
- e.crossOrigin,
291
- e.preloadStrategy,
292
- e.bufferingStrategy
293
- ]);
294
- const P = S(() => {
295
- const y = t.current;
296
- if (!y) return;
297
- const U = performance.now();
298
- if (e.enableTimeUpdateThrottling !== !1) {
299
- if (U - k.current < (e.timeUpdateThrottleMs || 100))
300
- return;
301
- k.current = U;
302
- }
303
- d(() => {
304
- w && T && T.setCurrentTime(y.currentTime);
305
- });
306
- }, [e.enableTimeUpdateThrottling, e.timeUpdateThrottleMs, w, T]), x = S(() => {
307
- d(() => {
308
- w && T && T.play(!0);
309
- }), e.onPlay?.();
310
- }, [w, T, e.onPlay]), O = S(() => {
311
- d(() => {
312
- w && T && T.pause(!0);
313
- }), e.onPause?.();
314
- }, [w, T, e.onPause]), V = S(() => {
315
- const y = t.current;
316
- y && d(() => {
317
- w && T && (T.setVolume(y.volume, !0), y.muted ? T.mute(!0) : T.unmute(!0));
318
- });
319
- }, [w, T]), R = S(() => {
320
- a(() => {
321
- });
322
- }, []), te = S(() => {
323
- }, []), c = S(() => {
324
- const y = t.current;
325
- y && d(() => {
326
- w && T && T.setBuffered(y.buffered);
327
- });
328
- }, [w, T]), N = S(() => {
329
- const y = performance.now();
330
- if (y - b.current > 0 && (l.current++, l.current >= 60)) {
331
- const z = Math.round(l.current * 1e3 / (y - b.current));
332
- D((Z) => ({
333
- ...Z,
334
- frameRate: z,
335
- droppedFrames: Math.max(0, 60 - z)
336
- })), l.current = 0, b.current = y;
337
- }
338
- }, []);
339
- G(() => {
340
- const y = t.current;
341
- if (!y) return;
342
- const U = [
343
- { event: "timeupdate", handler: P, passive: !0 },
344
- { event: "play", handler: x },
345
- { event: "pause", handler: O },
346
- { event: "volumechange", handler: V },
347
- { event: "seeking", handler: R },
348
- { event: "seeked", handler: te },
349
- { event: "progress", handler: c, passive: !0 },
350
- { event: "loadedmetadata", handler: () => N() },
351
- { event: "loadeddata", handler: () => N() }
352
- ];
353
- U.forEach(({ event: re, handler: se, passive: ae }) => {
354
- const ie = ae ? { passive: !0 } : {};
355
- y.addEventListener(re, se, ie);
356
- });
357
- let z;
358
- const Z = () => {
359
- N(), z = requestAnimationFrame(Z);
360
- };
361
- return e.enablePerformanceMonitoring && Z(), () => {
362
- U.forEach(({ event: re, handler: se }) => {
363
- y.removeEventListener(re, se);
364
- }), z && cancelAnimationFrame(z);
365
- };
366
- }, [
367
- P,
368
- x,
369
- O,
370
- V,
371
- R,
372
- te,
373
- c,
374
- N,
375
- e.enablePerformanceMonitoring
376
- ]);
377
- const Y = ue(() => {
378
- const y = async () => {
379
- const A = t.current;
380
- if (A)
381
- if (w && T)
382
- await T.play(!0);
383
- else
384
- try {
385
- await A.play();
386
- } catch (K) {
387
- console.error("Failed to play media:", K);
388
- }
389
- }, U = () => {
390
- const A = t.current;
391
- A && (w && T ? T.pause(!0) : A.pause());
392
- }, z = () => {
393
- r ? U() : y();
394
- }, Z = (A) => {
395
- const K = t.current;
396
- if (!K) return;
397
- const J = Number.isFinite(m) && m > 0 ? m : Number.isFinite(K.duration) ? K.duration : 0;
398
- if (J === 0) {
399
- console.warn("Cannot seek: duration is not available");
400
- return;
401
- }
402
- const ee = Math.max(0, Math.min(A, J));
403
- if (!Number.isFinite(ee)) {
404
- console.warn(`Computed non-finite seek time: ${ee}`);
405
- return;
406
- }
407
- w && T ? a(() => {
408
- T.seek(ee, !0);
409
- }) : fe(K, ee);
410
- }, re = (A) => {
411
- const K = t.current;
412
- if (!K) return;
413
- const J = Math.max(0, Math.min(1, A));
414
- w && T ? (C(J), d(() => {
415
- T.setVolume(J, !0);
416
- })) : K.volume = J;
417
- }, se = () => {
418
- const A = t.current;
419
- A && (w && T ? T.toggleMute(!0) : A.muted = !A.muted);
420
- }, ae = async () => {
421
- const A = n.current;
422
- if (!(!A || !document.fullscreenEnabled))
423
- try {
424
- await A.requestFullscreen(), w && T && T.enterFullscreen(!0);
425
- } catch (K) {
426
- console.error("Failed to enter fullscreen:", K);
427
- }
428
- }, ie = async () => {
429
- if (document.fullscreenElement)
430
- try {
431
- await document.exitFullscreen(), w && T && T.exitFullscreen(!0);
432
- } catch (A) {
433
- console.error("Failed to exit fullscreen:", A);
434
- }
435
- };
436
- return {
437
- play: y,
438
- pause: U,
439
- toggle: z,
440
- seek: Z,
441
- setCurrentTime: (A) => {
442
- const K = t.current;
443
- if (!K) return;
444
- const J = Number.isFinite(m) && m > 0 ? m : Number.isFinite(K.duration) ? K.duration : 0;
445
- if (J === 0) {
446
- console.warn("Cannot set currentTime: duration is not available");
447
- return;
448
- }
449
- const ee = Math.max(0, Math.min(A, J));
450
- if (!Number.isFinite(ee)) {
451
- console.warn(`Computed non-finite currentTime: ${ee}`);
452
- return;
453
- }
454
- fe(K, ee);
455
- },
456
- setVolume: re,
457
- mute: () => {
458
- const A = t.current;
459
- A && (w && T ? T.mute(!0) : A.muted = !0);
460
- },
461
- unmute: () => {
462
- const A = t.current;
463
- A && (w && T ? T.unmute(!0) : A.muted = !1);
464
- },
465
- toggleMute: se,
466
- enterFullscreen: ae,
467
- exitFullscreen: ie,
468
- toggleFullscreen: async () => {
469
- p ? await ie() : await ae();
470
- }
471
- };
472
- }, [
473
- r,
474
- p,
475
- m,
476
- w,
477
- T,
478
- d,
479
- a,
480
- C
481
- ]), ne = ue(
482
- () => ({
483
- isPlaying: L?.isPlaying ?? r,
484
- currentTime: L?.currentTime ?? g,
485
- duration: L?.actualState?.duration ?? m,
486
- volume: L?.volume ?? I,
487
- isMuted: L?.isMuted ?? h,
488
- isLoading: L?.isBuffering ?? F,
489
- isBuffering: L?.isBuffering ?? f,
490
- error: L?.actualState?.error ?? o,
491
- buffered: L?.actualState?.buffered ?? v,
492
- isFullscreen: L?.isFullscreen ?? p,
493
- progress: m > 0 ? g / m : 0,
494
- isTransitioning: s || u,
495
- canPlay: !F && !f && !o
496
- }),
497
- [
498
- L,
499
- r,
500
- g,
501
- m,
502
- I,
503
- h,
504
- F,
505
- f,
506
- o,
507
- v,
508
- p,
509
- s,
510
- u
511
- ]
512
- );
513
- return {
514
- // Refs
515
- mediaRef: t,
516
- containerRef: n,
517
- // State
518
- state: ne,
519
- actualState: L?.actualState,
520
- // Controls
521
- controls: Y,
522
- // Performance metrics
523
- performanceMetrics: $,
524
- isTransitioning: s || u,
525
- // Enhanced features
526
- actions: L,
527
- actionState: L,
528
- // Optimistic features
529
- optimisticState: L,
530
- isEnhanced: w
531
- };
532
- }
533
- function Le({
534
- enabled: e = !0,
535
- state: t,
536
- controls: n,
537
- seekStep: s = 10,
538
- volumeStep: d = 0.1
539
- }) {
540
- const u = (a) => {
541
- if (!e) return;
542
- const l = a.target;
543
- if (!(l.tagName === "INPUT" || l.tagName === "TEXTAREA" || l.contentEditable === "true"))
544
- switch (a.code) {
545
- case "Space":
546
- case "KeyK":
547
- a.preventDefault(), n.toggle();
548
- break;
549
- case "KeyM":
550
- a.preventDefault(), n.toggleMute();
551
- break;
552
- case "KeyF":
553
- a.preventDefault(), n.toggleFullscreen();
554
- break;
555
- case "ArrowLeft":
556
- a.preventDefault(), n.seek(Math.max(0, t.currentTime - s));
557
- break;
558
- case "ArrowRight":
559
- a.preventDefault(), n.seek(Math.min(t.duration, t.currentTime + s));
560
- break;
561
- case "ArrowUp":
562
- a.preventDefault(), n.setVolume(Math.min(1, t.volume + d));
563
- break;
564
- case "ArrowDown":
565
- a.preventDefault(), n.setVolume(Math.max(0, t.volume - d));
566
- break;
567
- case "Digit0":
568
- case "Digit1":
569
- case "Digit2":
570
- case "Digit3":
571
- case "Digit4":
572
- case "Digit5":
573
- case "Digit6":
574
- case "Digit7":
575
- case "Digit8":
576
- case "Digit9":
577
- a.preventDefault();
578
- const k = parseInt(a.code.replace("Digit", ""), 10) / 10;
579
- n.seek(t.duration * k);
580
- break;
581
- case "Home":
582
- a.preventDefault(), n.seek(0);
583
- break;
584
- case "End":
585
- a.preventDefault(), n.seek(t.duration);
586
- break;
587
- }
588
- };
589
- return G(() => {
590
- if (e)
591
- return document.addEventListener("keydown", u), () => {
592
- document.removeEventListener("keydown", u);
593
- };
594
- }, [e, u]), {
595
- handleKeyDown: u
596
- };
597
- }
598
- const $e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
599
- __proto__: null,
600
- useKeyboardControls: Le
601
- }, Symbol.toStringTag, { value: "Module" }));
602
- function He(e = {}) {
603
- const {
604
- maxMemoryUsage: t = 100,
605
- // 100MB default
606
- cleanupInterval: n = 3e4,
607
- // 30 seconds default
608
- enableGC: s = !0,
609
- monitorMemory: d = !0
610
- } = e;
611
- H(void 0);
612
- const u = H(/* @__PURE__ */ new Set()), a = H(
613
- /* @__PURE__ */ new Map()
614
- ), l = H(/* @__PURE__ */ new Set()), b = H(/* @__PURE__ */ new Set()), k = S(() => {
615
- if (typeof window > "u" || !("memory" in performance))
616
- return { used: 0, total: 0, limit: 0 };
617
- const f = performance.memory;
618
- return {
619
- used: f.usedJSHeapSize,
620
- total: f.totalJSHeapSize,
621
- limit: f.jsHeapSizeLimit
622
- };
623
- }, []), [M, w] = j.useState({
624
- used: 0,
625
- total: 0,
626
- limit: 0,
627
- usage: 0,
628
- isHighUsage: !1
629
- }), r = S(() => {
630
- l.current.forEach((f) => {
631
- clearTimeout(f);
632
- }), l.current.clear(), b.current.forEach((f) => {
633
- cancelAnimationFrame(f);
634
- }), b.current.clear(), u.current.forEach((f) => {
635
- f.disconnect();
636
- }), u.current.clear(), a.current.forEach((f, o) => {
637
- f.forEach(({ event: v, handler: p }) => {
638
- o.removeEventListener(v, p);
639
- });
640
- }), a.current.clear(), typeof window < "u" && "gc" in window && window.gc();
641
- }, []), g = S((f, o) => {
642
- const v = globalThis.setInterval(f, o);
643
- return l.current.add(v), () => {
644
- globalThis.clearInterval(v), l.current.delete(v);
645
- };
646
- }, []);
647
- G(() => {
648
- if (!d) return;
649
- const f = () => {
650
- const o = k(), v = o.used / 1024 / 1024, p = v > t;
651
- w({
652
- ...o,
653
- usage: v,
654
- isHighUsage: p
655
- }), p && s && r();
656
- };
657
- return f(), g(f, n);
658
- }, [d, k, t, s, n, r]);
659
- const m = S(
660
- (f, o, v, p) => (f.addEventListener(o, v, p), a.current.has(f) || a.current.set(f, []), a.current.get(f).push({ event: o, handler: v }), () => {
661
- f.removeEventListener(o, v);
662
- const E = a.current.get(f);
663
- if (E) {
664
- const L = E.findIndex((T) => T.event === o && T.handler === v);
665
- L > -1 && E.splice(L, 1), E.length === 0 && a.current.delete(f);
666
- }
667
- }),
668
- []
669
- ), i = S((f, o) => {
670
- const v = globalThis.setTimeout(f, o);
671
- return l.current.add(v), () => {
672
- globalThis.clearTimeout(v), l.current.delete(v);
673
- };
674
- }, []), h = S((f) => {
675
- const o = globalThis.requestAnimationFrame(f);
676
- return b.current.add(o), () => {
677
- globalThis.cancelAnimationFrame(o), b.current.delete(o);
678
- };
679
- }, []), F = S((f) => (u.current.add(f), () => {
680
- f.disconnect(), u.current.delete(f);
681
- }), []);
682
- return G(() => () => {
683
- r();
684
- }, [r]), {
685
- // Memory stats
686
- memoryStats: M,
687
- getMemoryUsage: k,
688
- // Cleanup functions
689
- performCleanup: r,
690
- // Safe API functions
691
- addEventListener: m,
692
- setInterval: g,
693
- setTimeout: i,
694
- requestAnimationFrame: h,
695
- addObserver: F,
696
- // Utilities
697
- formatBytes: (f) => {
698
- if (f === 0) return "0 Bytes";
699
- const o = 1024, v = ["Bytes", "KB", "MB", "GB"], p = Math.floor(Math.log(f) / Math.log(o));
700
- return parseFloat((f / Math.pow(o, p)).toFixed(2)) + " " + v[p];
701
- }
702
- };
703
- }
704
- function ke() {
705
- const [e, t] = W({
706
- isPlaying: !1,
707
- currentTime: 0,
708
- duration: 0,
709
- volume: 1,
710
- isMuted: !1,
711
- isLoading: !1,
712
- isFullscreen: !1,
713
- error: null,
714
- buffered: null
715
- }), n = (r) => {
716
- t((g) => ({ ...g, ...r }));
717
- };
718
- return {
719
- state: e,
720
- updateState: n,
721
- setPlaying: (r) => {
722
- n({ isPlaying: r });
723
- },
724
- setCurrentTime: (r) => {
725
- n({ currentTime: r });
726
- },
727
- setDuration: (r) => {
728
- n({ duration: r });
729
- },
730
- setVolume: (r) => {
731
- n({ volume: Math.max(0, Math.min(1, r)) });
732
- },
733
- setMuted: (r) => {
734
- n({ isMuted: r });
735
- },
736
- setLoading: (r) => {
737
- n({ isLoading: r });
738
- },
739
- setFullscreen: (r) => {
740
- n({ isFullscreen: r });
741
- },
742
- setError: (r) => {
743
- n({ error: r });
744
- },
745
- setBuffered: (r) => {
746
- n({ buffered: r });
747
- }
748
- };
749
- }
750
- function Me(e, t) {
751
- if (!Number.isFinite(t))
752
- return console.warn(`Attempted to set non-finite currentTime: ${t}`), !1;
753
- if (t < 0)
754
- return console.warn(`Attempted to set negative currentTime: ${t}`), !1;
755
- try {
756
- return e.currentTime = t, !0;
757
- } catch (n) {
758
- return console.error(`Failed to set currentTime to ${t}:`, n), !1;
759
- }
760
- }
761
- function Pe(e) {
762
- const t = H(null), n = H(null), {
763
- state: s,
764
- setPlaying: d,
765
- setCurrentTime: u,
766
- setDuration: a,
767
- setVolume: l,
768
- setMuted: b,
769
- setLoading: k,
770
- setFullscreen: M,
771
- setError: w,
772
- setBuffered: r
773
- } = ke();
774
- G(() => {
775
- const c = t.current;
776
- c && (e.volume !== void 0 && (c.volume = e.volume, l(e.volume)), e.muted !== void 0 && (c.muted = e.muted, b(e.muted)), e.autoPlay !== void 0 && (c.autoplay = e.autoPlay), e.loop !== void 0 && (c.loop = e.loop), e.preload !== void 0 && (c.preload = e.preload), e.crossOrigin !== void 0 && (c.crossOrigin = e.crossOrigin));
777
- }, [e, l, b]);
778
- const g = S(() => {
779
- d(!0), e.onPlay?.();
780
- }, [d, e]), m = S(() => {
781
- d(!1), e.onPause?.();
782
- }, [d, e]), i = S(() => {
783
- const c = t.current;
784
- c && (u(c.currentTime), e.onTimeUpdate?.(c.currentTime));
785
- }, [u, e]), h = S(() => {
786
- const c = t.current;
787
- c && (a(c.duration), e.onDurationChange?.(c.duration));
788
- }, [a, e]), F = S(() => {
789
- const c = t.current;
790
- c && (l(c.volume), b(c.muted), e.onVolumeChange?.(c.volume));
791
- }, [l, b, e]), f = S(() => {
792
- k(!0), w(null), e.onLoadStart?.();
793
- }, [k, w, e]), o = S(() => {
794
- k(!1), e.onLoadedData?.();
795
- }, [k, e]), v = S(() => {
796
- const c = t.current;
797
- if (!c) return;
798
- const N = c.error?.message || "An error occurred while loading the media";
799
- w(N), k(!1), e.onError?.(N);
800
- }, [w, k, e]), p = S(() => {
801
- d(!1), e.onEnded?.();
802
- }, [d, e]), E = S(() => {
803
- const c = t.current;
804
- c && r(c.buffered);
805
- }, [r]);
806
- G(() => {
807
- const c = t.current;
808
- if (c)
809
- return c.addEventListener("play", g), c.addEventListener("pause", m), c.addEventListener("timeupdate", i), c.addEventListener("durationchange", h), c.addEventListener("volumechange", F), c.addEventListener("loadstart", f), c.addEventListener("loadeddata", o), c.addEventListener("error", v), c.addEventListener("ended", p), c.addEventListener("progress", E), () => {
810
- c.removeEventListener("play", g), c.removeEventListener("pause", m), c.removeEventListener("timeupdate", i), c.removeEventListener("durationchange", h), c.removeEventListener("volumechange", F), c.removeEventListener("loadstart", f), c.removeEventListener("loadeddata", o), c.removeEventListener("error", v), c.removeEventListener("ended", p), c.removeEventListener("progress", E);
811
- };
812
- }, [
813
- g,
814
- m,
815
- i,
816
- h,
817
- F,
818
- f,
819
- o,
820
- v,
821
- p,
822
- E
823
- ]);
824
- const L = S(async () => {
825
- const c = t.current;
826
- if (c)
827
- try {
828
- await c.play();
829
- } catch (N) {
830
- console.error("Failed to play media:", N), w("Failed to play media");
831
- }
832
- }, [w]), T = S(() => {
833
- const c = t.current;
834
- c && c.pause();
835
- }, []), $ = S(() => {
836
- s.isPlaying ? T() : L();
837
- }, [s.isPlaying, T, L]), D = S((c) => {
838
- const N = t.current;
839
- if (!N) return;
840
- const Y = Number.isFinite(N.duration) ? N.duration : 0;
841
- if (Y === 0) {
842
- console.warn("Cannot seek: duration is not available");
843
- return;
844
- }
845
- const ne = Math.max(0, Math.min(c, Y));
846
- Me(N, ne);
847
- }, []), I = S((c) => {
848
- const N = t.current;
849
- if (!N) return;
850
- const Y = Math.max(0, Math.min(1, c));
851
- N.volume = Y;
852
- }, []), C = S(() => {
853
- const c = t.current;
854
- c && (c.muted = !0);
855
- }, []), P = S(() => {
856
- const c = t.current;
857
- c && (c.muted = !1);
858
- }, []), x = S(() => {
859
- const c = t.current;
860
- c && (c.muted = !c.muted);
861
- }, []), O = S(async () => {
862
- const c = n.current;
863
- if (!(!c || !document.fullscreenEnabled))
864
- try {
865
- await c.requestFullscreen(), M(!0);
866
- } catch (N) {
867
- console.error("Failed to enter fullscreen:", N);
868
- }
869
- }, [M]), V = S(async () => {
870
- if (document.fullscreenElement)
871
- try {
872
- await document.exitFullscreen(), M(!1);
873
- } catch (c) {
874
- console.error("Failed to exit fullscreen:", c);
875
- }
876
- }, [M]), R = S(() => {
877
- document.fullscreenElement ? V() : O();
878
- }, [V, O]);
879
- return G(() => {
880
- const c = () => {
881
- M(!!document.fullscreenElement);
882
- };
883
- return document.addEventListener("fullscreenchange", c), () => {
884
- document.removeEventListener("fullscreenchange", c);
885
- };
886
- }, [M]), {
887
- state: s,
888
- controls: {
889
- play: L,
890
- pause: T,
891
- toggle: $,
892
- seek: D,
893
- setCurrentTime: D,
894
- setVolume: I,
895
- mute: C,
896
- unmute: P,
897
- toggleMute: x,
898
- enterFullscreen: O,
899
- exitFullscreen: V,
900
- toggleFullscreen: R
901
- },
902
- mediaRef: t,
903
- containerRef: n
904
- };
905
- }
906
- const q = {
907
- mobile: 768,
908
- desktop: 1280
909
- };
910
- function he() {
911
- if (typeof window > "u") return "unknown";
912
- const e = window.navigator.userAgent.toLowerCase();
913
- return /iphone|ipad|ipod/.test(e) ? "ios" : /android/.test(e) ? "android" : /windows|mac|linux/.test(e) ? "desktop" : "unknown";
914
- }
915
- function pe() {
916
- return typeof window > "u" ? !1 : "ontouchstart" in window || navigator.maxTouchPoints > 0 || // @ts-ignore - for older browsers
917
- navigator.msMaxTouchPoints > 0;
918
- }
919
- function ge() {
920
- return typeof window > "u" ? !1 : "vibrate" in navigator || // @ts-ignore - for newer Vibration API
921
- "vibration" in navigator || // @ts-ignore - for iOS haptic feedback
922
- "ondevicemotion" in window;
923
- }
924
- function le() {
925
- const [e, t] = X.useState(() => {
926
- if (typeof window > "u")
927
- return {
928
- isMobile: !1,
929
- isTablet: !1,
930
- isDesktop: !0,
931
- isTouchDevice: !1,
932
- platform: "unknown",
933
- supportsHaptics: !1,
934
- screenSize: { width: 1920, height: 1080 },
935
- orientation: "landscape"
936
- };
937
- const n = window.innerWidth, s = window.innerHeight;
938
- return {
939
- isMobile: n < q.mobile,
940
- isTablet: n >= q.mobile && n < q.desktop,
941
- isDesktop: n >= q.desktop,
942
- isTouchDevice: pe(),
943
- platform: he(),
944
- supportsHaptics: ge(),
945
- screenSize: { width: n, height: s },
946
- orientation: n > s ? "landscape" : "portrait"
947
- };
948
- });
949
- return X.useEffect(() => {
950
- const n = () => {
951
- const a = window.innerWidth, l = window.innerHeight;
952
- t({
953
- isMobile: a < q.mobile,
954
- isTablet: a >= q.mobile && a < q.desktop,
955
- isDesktop: a >= q.desktop,
956
- isTouchDevice: pe(),
957
- platform: he(),
958
- supportsHaptics: ge(),
959
- screenSize: { width: a, height: l },
960
- orientation: a > l ? "landscape" : "portrait"
961
- });
962
- };
963
- window.addEventListener("resize", n), window.addEventListener("orientationchange", n);
964
- const s = window.matchMedia(`(max-width: ${q.mobile - 1}px)`), d = window.matchMedia(`(min-width: ${q.mobile}px) and (max-width: ${q.desktop - 1}px)`), u = window.matchMedia(`(min-width: ${q.desktop}px)`);
965
- return s.addEventListener("change", n), d.addEventListener("change", n), u.addEventListener("change", n), () => {
966
- window.removeEventListener("resize", n), window.removeEventListener("orientationchange", n), s.removeEventListener("change", n), d.removeEventListener("change", n), u.removeEventListener("change", n);
967
- };
968
- }, []), e;
969
- }
970
- function Ge() {
971
- const { platform: e, isMobile: t } = le();
972
- X.useEffect(() => {
973
- if (t) {
974
- if (e === "ios") {
975
- const n = (s) => {
976
- s.touches.length > 1 && s.preventDefault();
977
- };
978
- return document.addEventListener("touchstart", n, { passive: !1 }), document.body.style.webkitOverflowScrolling = "touch", () => {
979
- document.removeEventListener("touchstart", n);
980
- };
981
- }
982
- e === "android" && (document.body.style.touchAction = "manipulation"), document.documentElement.style.setProperty("--webkit-transform", "translateZ(0)"), document.documentElement.style.setProperty("--transform", "translateZ(0)");
983
- }
984
- }, [e, t]);
985
- }
986
- function Fe() {
987
- const { supportsHaptics: e } = le();
988
- return { triggerHaptic: X.useCallback((n = "light") => {
989
- if (!e) return;
990
- const d = {
991
- light: [10],
992
- medium: [20],
993
- heavy: [30],
994
- success: [10, 10, 10],
995
- warning: [20, 20],
996
- error: [50, 20, 50]
997
- }[n];
998
- "vibrate" in navigator && navigator.vibrate(d);
999
- }, [e]), supportsHaptics: e };
1000
- }
1001
- const De = {
1002
- enabledGestures: [
1003
- "tap",
1004
- "double-tap",
1005
- "long-press",
1006
- "swipe-left",
1007
- "swipe-right",
1008
- "swipe-up",
1009
- "swipe-down",
1010
- "pinch-in",
1011
- "pinch-out"
1012
- ],
1013
- tapThreshold: 200,
1014
- doubleTapThreshold: 300,
1015
- longPressThreshold: 500,
1016
- swipeThreshold: 50,
1017
- swipeVelocityThreshold: 0.5,
1018
- pinchThreshold: 0.1,
1019
- rotationThreshold: 15,
1020
- enableHapticFeedback: !0
1021
- };
1022
- function Ce(e, t, n = {}) {
1023
- const s = { ...De, ...n }, { isTouchDevice: d } = le(), { triggerHaptic: u } = Fe(), a = X.useRef({
1024
- isTracking: !1,
1025
- touches: [],
1026
- startTouches: []
1027
- }), l = (m) => ({
1028
- id: m.identifier,
1029
- x: m.clientX,
1030
- y: m.clientY,
1031
- timestamp: Date.now()
1032
- }), b = (m, i) => Math.sqrt(Math.pow(i.x - m.x, 2) + Math.pow(i.y - m.y, 2)), k = (m, i) => {
1033
- const h = Math.max(i.timestamp - m.timestamp, 1);
1034
- return {
1035
- x: (i.x - m.x) / h,
1036
- y: (i.y - m.y) / h
1037
- };
1038
- }, M = (m, i, h, F = {}) => ({
1039
- type: m,
1040
- startPoint: { x: i.x, y: i.y },
1041
- currentPoint: { x: h.x, y: h.y },
1042
- duration: h.timestamp - i.timestamp,
1043
- target: e.current,
1044
- preventDefault: () => {
1045
- },
1046
- ...F
1047
- }), w = X.useCallback(
1048
- (m) => {
1049
- if (!s.enabledGestures.length) return;
1050
- const i = Array.from(m.touches).map(l), h = a.current;
1051
- h.isTracking = !0, h.touches = i, h.startTouches = [...i], h.longPressTimer && clearTimeout(h.longPressTimer), i.length === 1 && s.enabledGestures.includes("long-press") && (h.longPressTimer = setTimeout(() => {
1052
- if (h.touches.length === 1 && i[0]) {
1053
- const F = M("long-press", i[0], i[0]);
1054
- t(F), s.enableHapticFeedback && u("heavy");
1055
- }
1056
- }, s.longPressThreshold)), i.length === 2 && i[0] && i[1] && (h.initialDistance = b(i[0], i[1]), h.initialScale = 1, h.lastScale = 1);
1057
- },
1058
- [s, t, u]
1059
- ), r = X.useCallback(
1060
- (m) => {
1061
- const i = a.current;
1062
- if (!i.isTracking) return;
1063
- const h = Array.from(m.touches).map(l);
1064
- if (i.touches = h, h.length === 2 && i.initialDistance && h[0] && h[1]) {
1065
- const F = b(h[0], h[1]), f = F / i.initialDistance;
1066
- if (Math.abs(f - (i.lastScale || 1)) > s.pinchThreshold) {
1067
- const v = f > (i.lastScale || 1) ? "pinch-out" : "pinch-in";
1068
- if (s.enabledGestures.includes(v)) {
1069
- const p = {
1070
- x: (h[0].x + h[1].x) / 2,
1071
- y: (h[0].y + h[1].y) / 2,
1072
- timestamp: Date.now()
1073
- }, E = {
1074
- x: ((i.startTouches[0]?.x ?? 0) + (i.startTouches[1]?.x ?? 0)) / 2,
1075
- y: ((i.startTouches[0]?.y ?? 0) + (i.startTouches[1]?.y ?? 0)) / 2,
1076
- timestamp: i.startTouches[0]?.timestamp ?? Date.now()
1077
- }, L = M(v, E, p, {
1078
- scale: f,
1079
- distance: F
1080
- });
1081
- t(L), i.lastScale = f;
1082
- }
1083
- }
1084
- }
1085
- if (i.longPressTimer && h.length === 1 && i.startTouches[0] && h[0]) {
1086
- const F = i.startTouches[0], f = h[0];
1087
- b(F, f) > s.swipeThreshold && (clearTimeout(i.longPressTimer), i.longPressTimer = void 0);
1088
- }
1089
- },
1090
- [s, t]
1091
- ), g = X.useCallback(
1092
- (m) => {
1093
- const i = a.current;
1094
- if (!i.isTracking) return;
1095
- const h = Array.from(m.changedTouches).map(l), F = Date.now();
1096
- if (i.longPressTimer && (clearTimeout(i.longPressTimer), i.longPressTimer = void 0), i.startTouches.length === 1 && h.length === 1 && i.startTouches[0] && h[0]) {
1097
- const f = i.startTouches[0], o = h[0], v = b(f, o), p = o.timestamp - f.timestamp;
1098
- if (v > s.swipeThreshold) {
1099
- const E = k(f, o), L = Math.abs(E.x), T = Math.abs(E.y);
1100
- if (L > s.swipeVelocityThreshold || T > s.swipeVelocityThreshold) {
1101
- let $;
1102
- if (L > T ? $ = E.x > 0 ? "swipe-right" : "swipe-left" : $ = E.y > 0 ? "swipe-down" : "swipe-up", s.enabledGestures.includes($)) {
1103
- const D = M($, f, o, {
1104
- velocity: E,
1105
- distance: v
1106
- });
1107
- t(D), s.enableHapticFeedback && u("light");
1108
- }
1109
- }
1110
- } else if (p < s.tapThreshold && v < s.swipeThreshold)
1111
- if (i.lastTap && F - i.lastTap.timestamp < s.doubleTapThreshold && b(
1112
- { ...i.lastTap.point },
1113
- o
1114
- ) < s.swipeThreshold) {
1115
- if (s.enabledGestures.includes("double-tap")) {
1116
- const E = M("double-tap", f, o);
1117
- t(E), s.enableHapticFeedback && u("medium");
1118
- }
1119
- i.lastTap = void 0;
1120
- } else {
1121
- if (s.enabledGestures.includes("tap")) {
1122
- const E = M("tap", f, o);
1123
- t(E), s.enableHapticFeedback && u("light");
1124
- }
1125
- i.lastTap = {
1126
- timestamp: F,
1127
- point: { x: o.x, y: o.y }
1128
- };
1129
- }
1130
- }
1131
- m.touches.length === 0 && (i.isTracking = !1, i.touches = [], i.startTouches = [], i.initialDistance = void 0, i.initialScale = void 0, i.lastScale = void 0);
1132
- },
1133
- [s, t, u]
1134
- );
1135
- return X.useEffect(() => {
1136
- const m = e.current;
1137
- if (!(!m || !d))
1138
- return m.addEventListener("touchstart", w, { passive: !1 }), m.addEventListener("touchmove", r, { passive: !1 }), m.addEventListener("touchend", g, { passive: !1 }), m.addEventListener("touchcancel", g, { passive: !1 }), () => {
1139
- m.removeEventListener("touchstart", w), m.removeEventListener("touchmove", r), m.removeEventListener("touchend", g), m.removeEventListener("touchcancel", g);
1140
- };
1141
- }, [w, r, g, d]), {
1142
- isGestureEnabled: d && s.enabledGestures.length > 0
1143
- };
1144
- }
1145
- function Ke(e, t) {
1146
- const n = X.useCallback(
1147
- (d) => {
1148
- const { type: u, distance: a, scale: l } = d;
1149
- switch (u) {
1150
- case "double-tap":
1151
- t.onPlayPause?.();
1152
- break;
1153
- case "swipe-left":
1154
- const b = Math.min((a || 0) / 10, 30);
1155
- t.onSeek?.("backward", b);
1156
- break;
1157
- case "swipe-right":
1158
- const k = Math.min((a || 0) / 10, 30);
1159
- t.onSeek?.("forward", k);
1160
- break;
1161
- case "swipe-up":
1162
- if (d.startPoint.x > (e.current?.clientWidth || 0) / 2) {
1163
- const M = Math.min((a || 0) / 100, 0.2);
1164
- t.onVolumeChange?.("up", M);
1165
- }
1166
- break;
1167
- case "swipe-down":
1168
- if (d.startPoint.x > (e.current?.clientWidth || 0) / 2) {
1169
- const M = Math.min((a || 0) / 100, 0.2);
1170
- t.onVolumeChange?.("down", M);
1171
- }
1172
- break;
1173
- case "pinch-out":
1174
- t.onZoom?.(l || 1);
1175
- break;
1176
- case "pinch-in":
1177
- t.onZoom?.(l || 1);
1178
- break;
1179
- case "long-press":
1180
- t.onToggleFullscreen?.();
1181
- break;
1182
- }
1183
- },
1184
- [t, e]
1185
- );
1186
- return Ce(e, n, {
1187
- enabledGestures: [
1188
- "tap",
1189
- "double-tap",
1190
- "long-press",
1191
- "swipe-left",
1192
- "swipe-right",
1193
- "swipe-up",
1194
- "swipe-down",
1195
- "pinch-in",
1196
- "pinch-out"
1197
- ],
1198
- enableHapticFeedback: !0,
1199
- swipeThreshold: 30,
1200
- swipeVelocityThreshold: 0.3
1201
- });
1202
- }
1203
- function xe({
1204
- subtitleSrc: e,
1205
- subtitleTracks: t = [],
1206
- defaultFontSize: n = "medium",
1207
- onLoadError: s
1208
- } = {}) {
1209
- const [d, u] = W(!1), [a, l] = W([]), [b, k] = W(""), [M, w] = W(null), [r, g] = W(n), [m, i] = W(null), [h, F] = W(!1), f = {
1210
- small: "text-sm",
1211
- medium: "text-base",
1212
- large: "text-lg"
1213
- }, o = !!(e || t && t.length > 0), v = (C) => {
1214
- const P = C.split(":"), x = P[2] ? parseFloat(P[2]) : 0, O = P[1] ? parseInt(P[1], 10) * 60 : 0;
1215
- return (P[0] ? parseInt(P[0], 10) * 3600 : 0) + O + x;
1216
- }, p = (C) => {
1217
- const [P, x] = C.split(","), O = (P || "").split(":"), V = x ? parseInt(x, 10) / 1e3 : 0, R = O[2] ? parseInt(O[2], 10) : 0, te = O[1] ? parseInt(O[1], 10) * 60 : 0;
1218
- return (O[0] ? parseInt(O[0], 10) * 3600 : 0) + te + R + V;
1219
- }, E = async (C) => {
1220
- F(!0), i(null);
1221
- try {
1222
- const P = await fetch(C);
1223
- if (!P.ok)
1224
- throw new Error(`Failed to load subtitles: ${P.status} ${P.statusText}`);
1225
- const x = await P.text(), O = [], V = x.split(`
1226
- `);
1227
- let R = 0;
1228
- const te = x.includes("WEBVTT") || C.endsWith(".vtt"), c = C.endsWith(".srt") || /^\d+$/.test(V[0]?.trim() || "");
1229
- if (te)
1230
- for (; R < V.length; ) {
1231
- if (V[R]?.includes("-->")) {
1232
- const [N, Y] = (V[R] || "").split("-->").map((z) => z.trim()), ne = v(N || ""), y = v(Y || "");
1233
- R++;
1234
- let U = "";
1235
- for (; R < V.length && V[R]?.trim() !== ""; )
1236
- U += (U ? " " : "") + V[R]?.trim(), R++;
1237
- U && O.push({ start: ne, end: y, text: U });
1238
- }
1239
- R++;
1240
- }
1241
- else if (c)
1242
- for (; R < V.length; ) {
1243
- if (/^\d+$/.test(V[R]?.trim() || "") && (R++, V[R]?.includes("-->"))) {
1244
- const [N, Y] = (V[R] || "").split("-->").map((z) => z.trim()), ne = p(N || ""), y = p(Y || "");
1245
- R++;
1246
- let U = "";
1247
- for (; R < V.length && V[R]?.trim() !== ""; )
1248
- U += (U ? " " : "") + V[R]?.trim(), R++;
1249
- U && O.push({ start: ne, end: y, text: U });
1250
- }
1251
- R++;
1252
- }
1253
- else
1254
- throw new Error("Unsupported subtitle format. Only VTT and SRT are supported.");
1255
- if (O.length === 0)
1256
- throw new Error("No subtitle cues found in file");
1257
- l(O), F(!1);
1258
- } catch (P) {
1259
- const x = P instanceof Error ? P : new Error("Failed to load subtitles");
1260
- console.error("Failed to load subtitles:", x), i(x), F(!1), l([]), s?.(x);
1261
- }
1262
- }, L = (C) => !d || a.length === 0 ? "" : a.find(
1263
- (x) => C >= x.start && C <= x.end
1264
- )?.text || "", T = () => {
1265
- u((C) => {
1266
- const P = !C;
1267
- if (P && !m) {
1268
- if (a.length === 0 && !h) {
1269
- const x = e || t[0]?.src;
1270
- x && (E(x), t[0] && w(t[0].id));
1271
- }
1272
- } else P || k("");
1273
- return P;
1274
- });
1275
- }, $ = (C) => {
1276
- if (!C) {
1277
- u(!1), w(null), k("");
1278
- return;
1279
- }
1280
- const P = t.find((x) => x.id === C);
1281
- P?.src && (w(C), E(P.src), u(!0));
1282
- }, D = (C) => {
1283
- g(C);
1284
- }, I = {
1285
- fontSize: f[r],
1286
- className: `${f[r]} font-medium`
1287
- };
1288
- return G(() => {
1289
- d || k("");
1290
- }, [d]), G(() => {
1291
- }, []), {
1292
- // State
1293
- subtitlesEnabled: d,
1294
- currentSubtitle: b,
1295
- subtitleCues: a,
1296
- currentTrackId: M,
1297
- fontSize: r,
1298
- loadError: m,
1299
- isLoading: h,
1300
- hasSubtitles: o,
1301
- // Actions
1302
- toggleSubtitles: T,
1303
- selectSubtitleTrack: $,
1304
- changeSubtitleFontSize: D,
1305
- setCurrentSubtitle: k,
1306
- // Utilities
1307
- getCurrentSubtitle: L,
1308
- getSubtitleStyles: I,
1309
- // Track info
1310
- availableTracks: t
1311
- };
1312
- }
1313
- const ze = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1314
- __proto__: null,
1315
- useEnhancedSubtitles: xe
1316
- }, Symbol.toStringTag, { value: "Module" }));
1317
- function ve(e, t) {
1318
- if (!Number.isFinite(t))
1319
- return console.warn(`Attempted to set non-finite currentTime: ${t}`), !1;
1320
- if (t < 0)
1321
- return console.warn(`Attempted to set negative currentTime: ${t}`), !1;
1322
- try {
1323
- return e.currentTime = t, !0;
1324
- } catch (n) {
1325
- return console.error(`Failed to set currentTime to ${t}:`, n), !1;
1326
- }
1327
- }
1328
- function We({
1329
- videoControls: e,
1330
- toggleSubtitles: t,
1331
- takeScreenshot: n,
1332
- duration: s
1333
- }) {
1334
- const d = (u) => {
1335
- const a = document.querySelector("video");
1336
- if (a)
1337
- switch (u.key.toLowerCase()) {
1338
- case " ":
1339
- case "k":
1340
- u.preventDefault(), e.togglePlay();
1341
- break;
1342
- case "j":
1343
- u.preventDefault(), e.seekBackward();
1344
- break;
1345
- case "l":
1346
- u.preventDefault(), e.seekForward();
1347
- break;
1348
- case "arrowleft":
1349
- u.preventDefault();
1350
- const l = Number.isFinite(a.currentTime) ? a.currentTime : 0, b = Math.max(0, l - 5);
1351
- ve(a, b);
1352
- break;
1353
- case "arrowright":
1354
- u.preventDefault();
1355
- const k = Number.isFinite(s) && s > 0 ? s : Number.isFinite(a.duration) ? a.duration : 0;
1356
- if (k === 0) {
1357
- console.warn("Cannot seek: duration is not available");
1358
- break;
1359
- }
1360
- const M = Number.isFinite(a.currentTime) ? a.currentTime : 0, w = Math.min(k, M + 5);
1361
- ve(a, w);
1362
- break;
1363
- case "arrowup":
1364
- u.preventDefault(), a.volume = Math.min(1, a.volume + 0.1);
1365
- break;
1366
- case "arrowdown":
1367
- u.preventDefault(), a.volume = Math.max(0, a.volume - 0.1);
1368
- break;
1369
- case "m":
1370
- u.preventDefault(), e.toggleMute();
1371
- break;
1372
- case "f":
1373
- u.preventDefault(), e.toggleFullscreen();
1374
- break;
1375
- case "c":
1376
- u.preventDefault(), t();
1377
- break;
1378
- case "s":
1379
- u.preventDefault(), n(u.ctrlKey || u.metaKey);
1380
- break;
1381
- }
1382
- };
1383
- G(() => (document.addEventListener("keydown", d), () => document.removeEventListener("keydown", d)), [d]);
1384
- }
1385
- function je(e, t) {
1386
- const [n, s] = W(!0), [d, u] = W(!1), a = H(null), l = () => {
1387
- s(!0), a.current && clearTimeout(a.current), e && !t && (a.current = setTimeout(() => {
1388
- s(!1);
1389
- }, 3e3));
1390
- }, b = () => {
1391
- l();
1392
- }, k = () => {
1393
- s(!0);
1394
- }, M = () => {
1395
- e && s(!1);
1396
- };
1397
- return G(() => (l(), () => {
1398
- a.current && clearTimeout(a.current);
1399
- }), [l]), {
1400
- controlsVisible: n,
1401
- showVolumeSlider: d,
1402
- setShowVolumeSlider: u,
1403
- handleMouseMove: b,
1404
- handleMouseEnter: k,
1405
- handleMouseLeave: M
1406
- };
1407
- }
1408
- function qe(e) {
1409
- return { takeScreenshot: (n = !1) => {
1410
- if (!e.current) return;
1411
- const s = e.current, d = document.createElement("canvas");
1412
- d.width = s.videoWidth, d.height = s.videoHeight;
1413
- const u = d.getContext("2d");
1414
- if (u)
1415
- try {
1416
- u.drawImage(s, 0, 0), d.toBlob((a) => {
1417
- if (!a) {
1418
- console.error("Failed to create blob from canvas");
1419
- return;
1420
- }
1421
- if (n)
1422
- if (navigator.clipboard && window.ClipboardItem) {
1423
- const l = new ClipboardItem({ "image/png": a });
1424
- navigator.clipboard.write([l]).catch((b) => {
1425
- console.error("Failed to copy to clipboard:", b);
1426
- });
1427
- } else
1428
- console.warn("Clipboard API not supported");
1429
- else {
1430
- const l = URL.createObjectURL(a), b = document.createElement("a");
1431
- b.href = l, b.download = `screenshot-${Date.now()}.png`, b.click(), URL.revokeObjectURL(l);
1432
- }
1433
- }, "image/png");
1434
- } catch (a) {
1435
- a instanceof Error && a.message.includes("tainted") ? (console.error(
1436
- "Canvas is tainted - video source may not have proper CORS headers. Try setting crossOrigin='anonymous' on the video element."
1437
- ), alert(
1438
- "Screenshot failed: The video source doesn't allow screenshots due to CORS policy. Please ensure the video server includes proper CORS headers or set crossOrigin='anonymous' on the video player."
1439
- )) : (console.error("Screenshot failed:", a), alert("Screenshot failed: " + (a instanceof Error ? a.message : "Unknown error")));
1440
- }
1441
- } };
1442
- }
1443
- function oe(e, t) {
1444
- if (!Number.isFinite(t))
1445
- return console.warn(`Attempted to set non-finite currentTime: ${t}`), !1;
1446
- if (t < 0)
1447
- return console.warn(`Attempted to set negative currentTime: ${t}`), !1;
1448
- try {
1449
- return e.currentTime = t, !0;
1450
- } catch (n) {
1451
- return console.error(`Failed to set currentTime to ${t}:`, n), !1;
1452
- }
1453
- }
1454
- function Ye(e) {
1455
- const t = H(null), [n, s] = W({
1456
- isPlaying: !1,
1457
- currentTime: 0,
1458
- duration: 0,
1459
- volume: 1,
1460
- isMuted: !1,
1461
- isFullscreen: !1,
1462
- isLoading: !0,
1463
- isSeeking: !1,
1464
- isBuffering: !1,
1465
- bufferedRanges: []
1466
- });
1467
- return G(() => {
1468
- const r = t.current;
1469
- if (!r) return;
1470
- const g = () => {
1471
- s((D) => ({ ...D, currentTime: r.currentTime }));
1472
- }, m = () => {
1473
- s((D) => ({ ...D, duration: r.duration }));
1474
- }, i = () => {
1475
- s((D) => ({ ...D, isPlaying: !0, isBuffering: !1 }));
1476
- }, h = () => {
1477
- s((D) => ({ ...D, isPlaying: !1 }));
1478
- }, F = () => {
1479
- s((D) => ({
1480
- ...D,
1481
- volume: r.volume,
1482
- isMuted: r.muted
1483
- }));
1484
- }, f = () => {
1485
- s((D) => ({ ...D, isLoading: !0 }));
1486
- }, o = () => {
1487
- s((D) => ({ ...D, isLoading: !1 }));
1488
- }, v = () => {
1489
- s((D) => ({ ...D, isSeeking: !0 }));
1490
- }, p = () => {
1491
- s((D) => ({ ...D, isSeeking: !1 }));
1492
- }, E = () => {
1493
- s((D) => ({ ...D, isBuffering: !0 }));
1494
- }, L = () => {
1495
- s((D) => ({ ...D, isBuffering: !1, isLoading: !1 }));
1496
- }, T = () => {
1497
- s((D) => ({ ...D, isLoading: !1, isBuffering: !1 }));
1498
- }, $ = () => {
1499
- if (!r.buffered || r.buffered.length === 0 || r.duration === 0) {
1500
- s((I) => ({ ...I, bufferedRanges: [] }));
1501
- return;
1502
- }
1503
- const D = [];
1504
- for (let I = 0; I < r.buffered.length; I++) {
1505
- const C = r.buffered.start(I), P = r.buffered.end(I);
1506
- D.push({
1507
- start: C,
1508
- end: P,
1509
- percentage: (P - C) / r.duration * 100
1510
- });
1511
- }
1512
- s((I) => ({ ...I, bufferedRanges: D }));
1513
- };
1514
- return r.addEventListener("timeupdate", g), r.addEventListener("loadedmetadata", m), r.addEventListener("play", i), r.addEventListener("pause", h), r.addEventListener("volumechange", F), r.addEventListener("loadstart", f), r.addEventListener("loadeddata", o), r.addEventListener("seeking", v), r.addEventListener("seeked", p), r.addEventListener("waiting", E), r.addEventListener("playing", L), r.addEventListener("canplay", T), r.addEventListener("progress", $), () => {
1515
- r.removeEventListener("timeupdate", g), r.removeEventListener("loadedmetadata", m), r.removeEventListener("play", i), r.removeEventListener("pause", h), r.removeEventListener("volumechange", F), r.removeEventListener("loadstart", f), r.removeEventListener("loadeddata", o), r.removeEventListener("seeking", v), r.removeEventListener("seeked", p), r.removeEventListener("waiting", E), r.removeEventListener("playing", L), r.removeEventListener("canplay", T), r.removeEventListener("progress", $);
1516
- };
1517
- }, []), {
1518
- videoRef: t,
1519
- state: n,
1520
- controls: {
1521
- togglePlay: () => {
1522
- const r = t.current;
1523
- r && (n.isPlaying ? r.pause() : r.play());
1524
- },
1525
- seekForward: (r = 10) => {
1526
- const g = t.current;
1527
- if (!g) return;
1528
- const m = Number.isFinite(g.duration) ? g.duration : Number.isFinite(n.duration) ? n.duration : 0;
1529
- if (m === 0) {
1530
- console.warn("Cannot seek forward: duration is not available");
1531
- return;
1532
- }
1533
- const i = Number.isFinite(g.currentTime) ? g.currentTime : 0, h = Math.min(m, i + r);
1534
- oe(g, h);
1535
- },
1536
- seekBackward: (r = 10) => {
1537
- const g = t.current;
1538
- if (!g) return;
1539
- const m = Number.isFinite(g.currentTime) ? g.currentTime : 0, i = Math.max(0, m - r);
1540
- oe(g, i);
1541
- },
1542
- toggleMute: () => {
1543
- const r = t.current;
1544
- r && (r.muted = !n.isMuted);
1545
- },
1546
- setVolume: (r) => {
1547
- const g = t.current;
1548
- g && (g.volume = r, r > 0 && n.isMuted && (g.muted = !1));
1549
- },
1550
- toggleFullscreen: () => {
1551
- const r = e.current;
1552
- r && (n.isFullscreen ? document.exitFullscreen && document.exitFullscreen() : r.requestFullscreen && r.requestFullscreen(), s((g) => ({ ...g, isFullscreen: !g.isFullscreen })));
1553
- },
1554
- seekTo: (r) => {
1555
- const g = t.current;
1556
- if (!g) return;
1557
- const m = Number.isFinite(g.duration) ? g.duration : Number.isFinite(n.duration) ? n.duration : 0;
1558
- if (m === 0) {
1559
- console.warn("Cannot seek: duration is not available");
1560
- return;
1561
- }
1562
- const i = Math.max(0, Math.min(m, r));
1563
- oe(g, i);
1564
- }
1565
- }
1566
- };
1567
- }
1568
- const Qe = (e, t = {}) => {
1569
- const {
1570
- trackUserBehavior: n = !0,
1571
- adaptToNetwork: s = !0,
1572
- strategy: d = "balanced",
1573
- maxPreloadItems: u = 3,
1574
- preloadRadius: a = 2
1575
- } = t, l = H({
1576
- mouseMovements: 0,
1577
- scrollEvents: 0,
1578
- keyPresses: 0,
1579
- focusEvents: 0,
1580
- timeOnPage: 0,
1581
- engagementScore: 0,
1582
- lastInteraction: Date.now()
1583
- }), b = H(null), k = H(/* @__PURE__ */ new Set()), M = H([]), w = S(() => {
1584
- const o = l.current, v = Math.min(o.timeOnPage / 6e4, 1), p = Math.min(
1585
- (o.mouseMovements + o.scrollEvents + o.keyPresses) / 100,
1586
- 1
1587
- );
1588
- return (v * 0.4 + p * 0.6) * 100;
1589
- }, []), r = S(
1590
- (o, v = 1) => {
1591
- const p = l.current;
1592
- p[o] = typeof p[o] == "number" ? p[o] + v : Date.now(), p.engagementScore = w(), p.lastInteraction = Date.now();
1593
- },
1594
- [w]
1595
- ), g = S(() => {
1596
- if (!b.current || !s)
1597
- return { type: "unknown", downlink: 10, effectiveType: "4g", saveData: !1 };
1598
- const o = b.current;
1599
- return {
1600
- type: o.type,
1601
- downlink: o.downlink || 10,
1602
- effectiveType: o.effectiveType || "4g",
1603
- saveData: o.saveData || !1,
1604
- rtt: o.rtt || 100
1605
- };
1606
- }, [s]), m = S(
1607
- (o, v, p = 0) => {
1608
- if (k.current.has(o.src))
1609
- return { shouldPreload: !1, priority: "low", reason: "Already preloaded" };
1610
- const E = Math.abs(v - p);
1611
- if (E > a)
1612
- return { shouldPreload: !1, priority: "low", reason: "Outside preload radius" };
1613
- const L = l.current, T = g(), $ = L.engagementScore, D = Date.now() - L.lastInteraction;
1614
- if (T.saveData)
1615
- return { shouldPreload: !1, priority: "low", reason: "Data saver mode" };
1616
- let I = !1, C = "medium", P = "";
1617
- switch (d) {
1618
- case "conservative":
1619
- I = $ > 70 && T.effectiveType !== "2g" && E === 1, C = I ? "medium" : "low", P = I ? "High engagement and optimal network" : "Conservative strategy";
1620
- break;
1621
- case "aggressive":
1622
- I = $ > 30 && T.effectiveType !== "slow-2g", C = $ > 70 ? "high" : $ > 50 ? "medium" : "low", P = I ? "Aggressive preloading" : "Low engagement";
1623
- break;
1624
- case "balanced":
1625
- default:
1626
- const x = T.effectiveType === "4g" ? 1 : T.effectiveType === "3g" ? 0.7 : 0.3, O = $ * x;
1627
- I = O > 40 && E <= 2, C = O > 70 ? "high" : O > 55 ? "medium" : "low", P = I ? `Balanced: score ${O.toFixed(1)}` : "Low adjusted score";
1628
- break;
1629
- }
1630
- if (I) {
1631
- const x = o.type;
1632
- (x === "hls" || x === "m3u8" || x === "application/x-mpegURL") && (C = C === "low" ? "medium" : "high"), D < 5e3 && (C = "high", P += " + Recent interaction"), (x === "mp4" || x === "webm" || x === "video/mp4" || x === "video/webm") && (C = C === "low" ? "medium" : C);
1633
- }
1634
- return { shouldPreload: I, priority: C, reason: P };
1635
- },
1636
- [d, a, g, w]
1637
- ), i = S(async (o, v) => {
1638
- try {
1639
- const p = document.createElement("link");
1640
- switch (p.rel = "preload", p.href = o.src, o.type) {
1641
- case "hls":
1642
- case "m3u8":
1643
- case "application/x-mpegURL":
1644
- p.as = "fetch";
1645
- break;
1646
- case "mp4":
1647
- case "webm":
1648
- case "video/mp4":
1649
- case "video/webm":
1650
- p.as = "video";
1651
- break;
1652
- case "mp3":
1653
- case "wav":
1654
- case "ogg":
1655
- case "audio/mpeg":
1656
- case "audio/wav":
1657
- case "audio/ogg":
1658
- p.as = "audio";
1659
- break;
1660
- default:
1661
- p.as = "fetch";
1662
- }
1663
- p.crossOrigin = "anonymous", document.head.appendChild(p), k.current.add(o.src), console.debug(`Preloaded: ${o.src} (${v})`), setTimeout(() => {
1664
- document.head.contains(p) && document.head.removeChild(p);
1665
- }, 3e4);
1666
- } catch (p) {
1667
- console.warn("Failed to preload source:", o.src, p);
1668
- }
1669
- }, []), h = S(() => {
1670
- if (M.current.length === 0) return;
1671
- const v = [...M.current].sort((p, E) => E.priority - p.priority).slice(0, u);
1672
- M.current = [], v.forEach(({ source: p, priority: E }) => {
1673
- i(p, E);
1674
- });
1675
- }, [u, i]), F = S(
1676
- (o = 0) => {
1677
- M.current = [], e.forEach((v, p) => {
1678
- const E = m(v, p, o);
1679
- if (E.shouldPreload) {
1680
- const L = E.priority === "high" ? 3 : E.priority === "medium" ? 2 : 1;
1681
- M.current.push({ source: v, priority: L });
1682
- }
1683
- }), h();
1684
- },
1685
- [e, m, h]
1686
- );
1687
- return G(() => {
1688
- if (!n) return;
1689
- const o = () => r("mouseMovements"), v = () => r("scrollEvents"), p = () => r("keyPresses"), E = () => r("focusEvents");
1690
- document.addEventListener("mousemove", o, { passive: !0 }), document.addEventListener("scroll", v, { passive: !0 }), document.addEventListener("keydown", p, { passive: !0 }), document.addEventListener("focusin", E, { passive: !0 });
1691
- const L = setInterval(() => {
1692
- r("timeOnPage", 1);
1693
- }, 1e3);
1694
- return () => {
1695
- document.removeEventListener("mousemove", o), document.removeEventListener("scroll", v), document.removeEventListener("keydown", p), document.removeEventListener("focusin", E), clearInterval(L);
1696
- };
1697
- }, [n, r]), G(() => {
1698
- if (!s || !("connection" in navigator)) return;
1699
- const o = navigator.connection;
1700
- b.current = o;
1701
- const v = () => {
1702
- F();
1703
- };
1704
- return o.addEventListener("change", v), () => {
1705
- o.removeEventListener("change", v);
1706
- };
1707
- }, [s, F]), G(() => {
1708
- F();
1709
- }, [F]), ue(
1710
- () => ({
1711
- /**
1712
- * Manually trigger preloading for specific index
1713
- */
1714
- preloadAtIndex: (o) => {
1715
- F(o);
1716
- },
1717
- /**
1718
- * Get current user behavior data
1719
- */
1720
- getUserBehavior: () => ({ ...l.current }),
1721
- /**
1722
- * Get current network conditions
1723
- */
1724
- getNetworkConditions: g,
1725
- /**
1726
- * Clear preloaded items cache
1727
- */
1728
- clearCache: () => {
1729
- k.current.clear();
1730
- },
1731
- /**
1732
- * Get preloading statistics
1733
- */
1734
- getStats: () => ({
1735
- preloadedItems: k.current.size,
1736
- engagementScore: l.current.engagementScore,
1737
- queueLength: M.current.length,
1738
- maxPreloadItems: u
1739
- })
1740
- }),
1741
- [F, g, u]
1742
- );
1743
- };
1744
- function Re(e) {
1745
- const [t, n] = W(!1), [s, d] = W([]), [u, a] = W(""), l = (w) => {
1746
- const r = w.split(":"), g = r[2] ? parseFloat(r[2]) : 0, m = r[1] ? parseInt(r[1], 10) * 60 : 0;
1747
- return (r[0] ? parseInt(r[0], 10) * 3600 : 0) + m + g;
1748
- }, b = async (w) => {
1749
- try {
1750
- const g = await (await fetch(w)).text(), m = [], i = g.split(`
1751
- `);
1752
- let h = 0;
1753
- for (; h < i.length; ) {
1754
- if (i[h]?.includes("-->")) {
1755
- const [F, f] = (i[h] || "").split("-->").map((E) => E.trim()), o = l(F || ""), v = l(f || "");
1756
- h++;
1757
- let p = "";
1758
- for (; h < i.length && i[h]?.trim() !== ""; )
1759
- p += (p ? " " : "") + i[h]?.trim(), h++;
1760
- p && m.push({ start: o, end: v, text: p });
1761
- }
1762
- h++;
1763
- }
1764
- d(m);
1765
- } catch (r) {
1766
- console.error("Failed to load subtitles:", r);
1767
- }
1768
- }, k = (w) => !t || s.length === 0 ? "" : s.find(
1769
- (g) => w >= g.start && w <= g.end
1770
- )?.text || "", M = () => {
1771
- n((w) => {
1772
- const r = !w;
1773
- return r && e && s.length === 0 ? b(e) : r || a(""), r;
1774
- });
1775
- };
1776
- return G(() => {
1777
- t || a("");
1778
- }, [t]), {
1779
- subtitlesEnabled: t,
1780
- currentSubtitle: u,
1781
- toggleSubtitles: M,
1782
- getCurrentSubtitle: k,
1783
- setCurrentSubtitle: a
1784
- };
1785
- }
1786
- function Xe(e) {
1787
- return Te("useVideoPlayer", "useMediaPlayer (the primary media player hook)"), Pe(e);
1788
- }
1789
- function Ze(e) {
1790
- return Te("useEnhancedSubtitles", "useSubtitles (the current subtitle hook)"), Re(e);
1791
- }
1792
- export {
1793
- Ge as a,
1794
- Ke as b,
1795
- Ye as c,
1796
- xe as d,
1797
- je as e,
1798
- We as f,
1799
- qe as g,
1800
- Be as h,
1801
- He as i,
1802
- Le as j,
1803
- Pe as k,
1804
- ke as l,
1805
- be as m,
1806
- ye as n,
1807
- Qe as o,
1808
- Ce as p,
1809
- Re as q,
1810
- Xe as r,
1811
- Ze as s,
1812
- $e as t,
1813
- le as u,
1814
- ze as v
1815
- };
1816
- //# sourceMappingURL=hooks-Bpi-jDiO.js.map