@hh.ru/magritte-ui-video 1.0.1 → 1.0.3
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/Video.js +44 -5
- package/Video.js.map +1 -1
- package/VideoControls.js +4 -4
- package/VideoControls.js.map +1 -1
- package/VideoPlayer.js +13 -9
- package/VideoPlayer.js.map +1 -1
- package/index.css +64 -61
- package/index.js +2 -1
- package/index.js.map +1 -1
- package/internal/ControlButton.js +1 -1
- package/internal/Scrubber.js +1 -1
- package/internal/SeekIndicator.js +1 -1
- package/internal/VolumeSlider.js +1 -1
- package/internal/context.d.ts +9 -0
- package/internal/context.js.map +1 -1
- package/internal/store.d.ts +46 -1
- package/internal/store.js +188 -35
- package/internal/store.js.map +1 -1
- package/internal/useViewportVisibility.d.ts +6 -0
- package/internal/useViewportVisibility.js +31 -0
- package/internal/useViewportVisibility.js.map +1 -0
- package/package.json +2 -2
- package/types.d.ts +34 -0
- package/video-B0giLQLN.js +5 -0
- package/video-B0giLQLN.js.map +1 -0
- package/video-C-iklAZX.js +0 -5
- package/video-C-iklAZX.js.map +0 -1
package/internal/store.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import './../index.css';
|
|
2
2
|
const PLAYBACK_RATES = [1, 1.5, 2];
|
|
3
|
+
const AUDIBLE_EVENT = "magritte-video-audible";
|
|
3
4
|
const BOOST_RATE = 2;
|
|
4
5
|
const CONTROLS_HIDE_DELAY_MS = 4e3;
|
|
5
6
|
const INITIAL_STATE = {
|
|
6
7
|
status: "idle",
|
|
7
8
|
waiting: false,
|
|
9
|
+
retrying: false,
|
|
8
10
|
duration: null,
|
|
9
11
|
size: null,
|
|
10
12
|
muted: false,
|
|
@@ -37,8 +39,24 @@ const pickSource = (video, { src, sources }) => {
|
|
|
37
39
|
return playable?.src ?? src;
|
|
38
40
|
};
|
|
39
41
|
const toDuration = (value) => Number.isFinite(value) && value > 0 ? value : null;
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
+
const clampVolume = (volume) => Math.min(Math.max(volume, 0), 1);
|
|
43
|
+
const createVideoStore = ({
|
|
44
|
+
getCallbacks,
|
|
45
|
+
getOptions,
|
|
46
|
+
defaultMuted = false,
|
|
47
|
+
defaultVolume = 1,
|
|
48
|
+
...initialSource
|
|
49
|
+
}) => {
|
|
50
|
+
const isAutoPlay = () => {
|
|
51
|
+
const { autoPlay, interactive } = getOptions();
|
|
52
|
+
return autoPlay || !interactive;
|
|
53
|
+
};
|
|
54
|
+
let state = {
|
|
55
|
+
...INITIAL_STATE,
|
|
56
|
+
// автовоспроизведение и неинтерактивный режим — без звука
|
|
57
|
+
muted: defaultMuted || isAutoPlay(),
|
|
58
|
+
volume: Number.isFinite(defaultVolume) ? clampVolume(defaultVolume) : 1
|
|
59
|
+
};
|
|
42
60
|
let source = initialSource;
|
|
43
61
|
let sourceKey = getSourceKey(initialSource);
|
|
44
62
|
let video = null;
|
|
@@ -50,8 +68,29 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
50
68
|
let hideTimer = null;
|
|
51
69
|
let holds = 0;
|
|
52
70
|
let hideWhenPaused = false;
|
|
71
|
+
let host = null;
|
|
72
|
+
let unsubscribeHost = null;
|
|
73
|
+
let hostPin = null;
|
|
74
|
+
let boostHidesControls = false;
|
|
75
|
+
let visible = null;
|
|
76
|
+
let pausedByViewport = false;
|
|
77
|
+
let soundChangedByUser = false;
|
|
78
|
+
const audibleToken = {};
|
|
53
79
|
const listeners = /* @__PURE__ */ new Set();
|
|
54
80
|
const timeListeners = /* @__PURE__ */ new Set();
|
|
81
|
+
const getControlsPin = () => {
|
|
82
|
+
if (state.boosted && boostHidesControls) {
|
|
83
|
+
return "hidden";
|
|
84
|
+
}
|
|
85
|
+
return holds > 0 ? "shown" : null;
|
|
86
|
+
};
|
|
87
|
+
const syncControlsPin = () => {
|
|
88
|
+
const pin = getControlsPin();
|
|
89
|
+
if (host && pin !== hostPin) {
|
|
90
|
+
hostPin = pin;
|
|
91
|
+
host.setPin(pin);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
55
94
|
const setState = (patch) => {
|
|
56
95
|
const keys = Object.keys(patch);
|
|
57
96
|
if (keys.every((key) => patch[key] === state[key])) {
|
|
@@ -59,6 +98,7 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
59
98
|
}
|
|
60
99
|
state = { ...state, ...patch };
|
|
61
100
|
listeners.forEach((listener) => listener());
|
|
101
|
+
syncControlsPin();
|
|
62
102
|
};
|
|
63
103
|
const getTime = () => {
|
|
64
104
|
if (!video) {
|
|
@@ -108,7 +148,7 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
108
148
|
const canHide = () => holds === 0 && (state.status === "playing" || hideWhenPaused && state.status === "paused");
|
|
109
149
|
const scheduleHide = () => {
|
|
110
150
|
clearHideTimer();
|
|
111
|
-
if (!canHide()) {
|
|
151
|
+
if (host || !canHide()) {
|
|
112
152
|
return;
|
|
113
153
|
}
|
|
114
154
|
hideTimer = setTimeout(() => {
|
|
@@ -119,6 +159,10 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
119
159
|
}, CONTROLS_HIDE_DELAY_MS);
|
|
120
160
|
};
|
|
121
161
|
const showControls = () => {
|
|
162
|
+
if (host) {
|
|
163
|
+
host.notifyActivity();
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
122
166
|
setState({ controlsVisible: true });
|
|
123
167
|
scheduleHide();
|
|
124
168
|
};
|
|
@@ -136,6 +180,7 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
136
180
|
if (!state.boosted) {
|
|
137
181
|
return;
|
|
138
182
|
}
|
|
183
|
+
boostHidesControls = false;
|
|
139
184
|
setState({ boosted: false });
|
|
140
185
|
if (video) {
|
|
141
186
|
video.playbackRate = state.rate;
|
|
@@ -145,9 +190,61 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
145
190
|
endBoost();
|
|
146
191
|
stopTicking();
|
|
147
192
|
clearHideTimer();
|
|
148
|
-
setState({ status: "error", waiting: false });
|
|
193
|
+
setState({ status: "error", waiting: false, retrying: false });
|
|
149
194
|
getCallbacks().onError?.(error);
|
|
150
195
|
};
|
|
196
|
+
const isAudible = () => !!video && !video.paused && !video.muted && video.volume > 0;
|
|
197
|
+
const claimAudio = () => {
|
|
198
|
+
if (isAudible()) {
|
|
199
|
+
document.dispatchEvent(new CustomEvent(AUDIBLE_EVENT, { detail: audibleToken }));
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
const onAudibleElsewhere = (event) => {
|
|
203
|
+
if (event.detail !== audibleToken && isAudible()) {
|
|
204
|
+
video?.pause();
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
const play = () => {
|
|
208
|
+
if (!video) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
pausedByViewport = false;
|
|
212
|
+
started = true;
|
|
213
|
+
enterLoading();
|
|
214
|
+
if (video.ended) {
|
|
215
|
+
video.currentTime = 0;
|
|
216
|
+
}
|
|
217
|
+
const element = video;
|
|
218
|
+
Promise.resolve(element.play()).catch(() => {
|
|
219
|
+
if (video !== element || state.status === "error" || !element.paused) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (state.status === "loading") {
|
|
223
|
+
started = element.currentTime > 0;
|
|
224
|
+
setState({ status: started ? "paused" : "idle", waiting: false, retrying: false });
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
const tryAutoPlay = () => {
|
|
229
|
+
if (!video || visible !== true || !isAutoPlay()) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (state.status !== "idle" && !(state.status === "paused" && pausedByViewport)) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
pausedByViewport = false;
|
|
236
|
+
if (!soundChangedByUser || !getOptions().interactive) {
|
|
237
|
+
video.muted = true;
|
|
238
|
+
}
|
|
239
|
+
play();
|
|
240
|
+
};
|
|
241
|
+
const autoPause = () => {
|
|
242
|
+
if (!video || !getOptions().autoPause || video.paused) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
video.pause();
|
|
246
|
+
pausedByViewport = true;
|
|
247
|
+
};
|
|
151
248
|
const handlers = {
|
|
152
249
|
loadedmetadata: () => {
|
|
153
250
|
if (!video) {
|
|
@@ -165,6 +262,7 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
165
262
|
play: () => {
|
|
166
263
|
started = true;
|
|
167
264
|
enterLoading();
|
|
265
|
+
claimAudio();
|
|
168
266
|
getCallbacks().onPlay?.();
|
|
169
267
|
},
|
|
170
268
|
playing: () => {
|
|
@@ -172,7 +270,7 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
172
270
|
origin = video.currentTime;
|
|
173
271
|
}
|
|
174
272
|
const wasPlaying = state.status === "playing";
|
|
175
|
-
setState({ status: "playing", waiting: false });
|
|
273
|
+
setState({ status: "playing", waiting: false, retrying: false });
|
|
176
274
|
startTicking();
|
|
177
275
|
if (!wasPlaying) {
|
|
178
276
|
scheduleHide();
|
|
@@ -187,8 +285,8 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
187
285
|
if (!video || video.ended || state.status === "error") {
|
|
188
286
|
return;
|
|
189
287
|
}
|
|
190
|
-
setState({ status: started ? "paused" : "idle", waiting: false,
|
|
191
|
-
|
|
288
|
+
setState({ status: started ? "paused" : "idle", waiting: false, retrying: false });
|
|
289
|
+
showControls();
|
|
192
290
|
getCallbacks().onPause?.();
|
|
193
291
|
},
|
|
194
292
|
ended: () => {
|
|
@@ -196,12 +294,18 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
196
294
|
stopTicking();
|
|
197
295
|
emitTime();
|
|
198
296
|
clearHideTimer();
|
|
199
|
-
setState({ status: "ended", waiting: false
|
|
297
|
+
setState({ status: "ended", waiting: false });
|
|
298
|
+
if (!host) {
|
|
299
|
+
setState({ controlsVisible: true });
|
|
300
|
+
}
|
|
200
301
|
getCallbacks().onEnded?.();
|
|
201
302
|
},
|
|
202
303
|
error: () => fail(video?.error ?? new Error("Video loading error")),
|
|
203
304
|
volumechange: () => {
|
|
204
|
-
|
|
305
|
+
if (video) {
|
|
306
|
+
setState({ muted: video.muted, volume: video.volume });
|
|
307
|
+
claimAudio();
|
|
308
|
+
}
|
|
205
309
|
},
|
|
206
310
|
ratechange: () => {
|
|
207
311
|
if (video && !state.boosted) {
|
|
@@ -226,6 +330,11 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
226
330
|
([name, handler]) => add ? element.addEventListener(name, handler) : element.removeEventListener(name, handler)
|
|
227
331
|
);
|
|
228
332
|
};
|
|
333
|
+
const restoreRate = () => {
|
|
334
|
+
if (video) {
|
|
335
|
+
video.playbackRate = state.rate;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
229
338
|
const applySource = () => {
|
|
230
339
|
if (!video) {
|
|
231
340
|
return;
|
|
@@ -242,6 +351,7 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
242
351
|
}
|
|
243
352
|
}
|
|
244
353
|
});
|
|
354
|
+
restoreRate();
|
|
245
355
|
return;
|
|
246
356
|
}
|
|
247
357
|
const url = pickSource(video, source);
|
|
@@ -251,6 +361,7 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
251
361
|
video.removeAttribute("src");
|
|
252
362
|
}
|
|
253
363
|
video.load();
|
|
364
|
+
restoreRate();
|
|
254
365
|
};
|
|
255
366
|
const resetState = () => {
|
|
256
367
|
endBoost();
|
|
@@ -258,6 +369,7 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
258
369
|
clearHideTimer();
|
|
259
370
|
started = false;
|
|
260
371
|
origin = null;
|
|
372
|
+
pausedByViewport = false;
|
|
261
373
|
state = { ...INITIAL_STATE, ...pickPreserved(state) };
|
|
262
374
|
listeners.forEach((listener) => listener());
|
|
263
375
|
};
|
|
@@ -293,6 +405,7 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
293
405
|
endBoost();
|
|
294
406
|
if (video) {
|
|
295
407
|
listen(video, false);
|
|
408
|
+
document.removeEventListener(AUDIBLE_EVENT, onAudibleElsewhere);
|
|
296
409
|
detachMedia?.();
|
|
297
410
|
detachMedia = null;
|
|
298
411
|
stopTicking();
|
|
@@ -302,10 +415,13 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
302
415
|
return;
|
|
303
416
|
}
|
|
304
417
|
listen(video, true);
|
|
305
|
-
|
|
306
|
-
|
|
418
|
+
document.addEventListener(AUDIBLE_EVENT, onAudibleElsewhere);
|
|
419
|
+
const { muted, volume } = state;
|
|
420
|
+
video.muted = muted;
|
|
421
|
+
video.volume = volume;
|
|
422
|
+
video.loop = getOptions().loop || !getOptions().interactive;
|
|
307
423
|
applySource();
|
|
308
|
-
|
|
424
|
+
tryAutoPlay();
|
|
309
425
|
},
|
|
310
426
|
getVideoElement: () => video,
|
|
311
427
|
setSource: (nextSource) => {
|
|
@@ -317,28 +433,11 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
317
433
|
sourceKey = nextKey;
|
|
318
434
|
resetState();
|
|
319
435
|
applySource();
|
|
436
|
+
tryAutoPlay();
|
|
320
437
|
},
|
|
321
|
-
play
|
|
322
|
-
if (!video) {
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
started = true;
|
|
326
|
-
enterLoading();
|
|
327
|
-
if (video.ended) {
|
|
328
|
-
video.currentTime = 0;
|
|
329
|
-
}
|
|
330
|
-
const element = video;
|
|
331
|
-
Promise.resolve(element.play()).catch(() => {
|
|
332
|
-
if (video !== element || state.status === "error" || !element.paused) {
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
if (state.status === "loading") {
|
|
336
|
-
started = element.currentTime > 0;
|
|
337
|
-
setState({ status: started ? "paused" : "idle", waiting: false });
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
},
|
|
438
|
+
play,
|
|
341
439
|
pause: () => {
|
|
440
|
+
pausedByViewport = false;
|
|
342
441
|
video?.pause();
|
|
343
442
|
},
|
|
344
443
|
seek: (seconds) => {
|
|
@@ -355,11 +454,34 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
355
454
|
store.seek(video.currentTime + seconds);
|
|
356
455
|
}
|
|
357
456
|
},
|
|
457
|
+
setVisible: (nextVisible) => {
|
|
458
|
+
if (visible === nextVisible) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
visible = nextVisible;
|
|
462
|
+
if (visible) {
|
|
463
|
+
tryAutoPlay();
|
|
464
|
+
} else if (visible === false) {
|
|
465
|
+
autoPause();
|
|
466
|
+
}
|
|
467
|
+
},
|
|
468
|
+
syncOptions: () => {
|
|
469
|
+
if (!video) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
const { loop, interactive } = getOptions();
|
|
473
|
+
video.loop = loop || !interactive;
|
|
474
|
+
if (!interactive) {
|
|
475
|
+
video.muted = true;
|
|
476
|
+
}
|
|
477
|
+
tryAutoPlay();
|
|
478
|
+
},
|
|
358
479
|
retry: () => {
|
|
359
480
|
if (!video) {
|
|
360
481
|
return;
|
|
361
482
|
}
|
|
362
483
|
resetState();
|
|
484
|
+
setState({ retrying: true });
|
|
363
485
|
applySource();
|
|
364
486
|
store.play();
|
|
365
487
|
},
|
|
@@ -368,13 +490,14 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
368
490
|
return;
|
|
369
491
|
}
|
|
370
492
|
if (state.status === "playing" || state.status === "loading" && !video.paused) {
|
|
371
|
-
|
|
493
|
+
store.pause();
|
|
372
494
|
return;
|
|
373
495
|
}
|
|
374
496
|
store.play();
|
|
375
497
|
},
|
|
376
498
|
setMuted: (muted) => {
|
|
377
499
|
if (video) {
|
|
500
|
+
soundChangedByUser = true;
|
|
378
501
|
video.muted = muted;
|
|
379
502
|
}
|
|
380
503
|
},
|
|
@@ -382,7 +505,8 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
382
505
|
if (!video) {
|
|
383
506
|
return;
|
|
384
507
|
}
|
|
385
|
-
|
|
508
|
+
soundChangedByUser = true;
|
|
509
|
+
const next = clampVolume(volume);
|
|
386
510
|
video.volume = next;
|
|
387
511
|
video.muted = next === 0;
|
|
388
512
|
},
|
|
@@ -395,6 +519,10 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
395
519
|
},
|
|
396
520
|
notifyActivity: showControls,
|
|
397
521
|
toggleControls: () => {
|
|
522
|
+
if (host) {
|
|
523
|
+
host.toggle();
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
398
526
|
if (state.controlsVisible && canHide()) {
|
|
399
527
|
clearHideTimer();
|
|
400
528
|
setState({ controlsVisible: false });
|
|
@@ -410,6 +538,10 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
410
538
|
},
|
|
411
539
|
holdControls: (hold) => {
|
|
412
540
|
holds = Math.max(0, holds + (hold ? 1 : -1));
|
|
541
|
+
if (host) {
|
|
542
|
+
syncControlsPin();
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
413
545
|
if (holds > 0) {
|
|
414
546
|
clearHideTimer();
|
|
415
547
|
setState({ controlsVisible: true });
|
|
@@ -417,6 +549,26 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
417
549
|
scheduleHide();
|
|
418
550
|
}
|
|
419
551
|
},
|
|
552
|
+
setControlsVisibilityHost: (nextHost) => {
|
|
553
|
+
if (host === nextHost) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
unsubscribeHost?.();
|
|
557
|
+
unsubscribeHost = null;
|
|
558
|
+
if (host && hostPin !== null) {
|
|
559
|
+
host.setPin(null);
|
|
560
|
+
}
|
|
561
|
+
hostPin = null;
|
|
562
|
+
host = nextHost;
|
|
563
|
+
clearHideTimer();
|
|
564
|
+
if (!host) {
|
|
565
|
+
showControls();
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
unsubscribeHost = host.subscribe((visible2) => setState({ controlsVisible: visible2 }));
|
|
569
|
+
setState({ controlsVisible: host.isVisible() });
|
|
570
|
+
syncControlsPin();
|
|
571
|
+
},
|
|
420
572
|
attachRoot: (element) => {
|
|
421
573
|
if (root === element) {
|
|
422
574
|
return;
|
|
@@ -460,7 +612,8 @@ const createVideoStore = ({ getCallbacks, ...initialSource }) => {
|
|
|
460
612
|
}
|
|
461
613
|
if (hideControls) {
|
|
462
614
|
clearHideTimer();
|
|
463
|
-
|
|
615
|
+
boostHidesControls = true;
|
|
616
|
+
setState(host ? { boosted: true } : { boosted: true, controlsVisible: false });
|
|
464
617
|
} else {
|
|
465
618
|
setState({ boosted: true });
|
|
466
619
|
}
|
package/internal/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sources":["src/internal/store.ts"],"sourcesContent":["import {\n type VideoAttachMedia,\n type VideoProps,\n type VideoSource,\n type VideoStatus,\n} from '@hh.ru/magritte-ui-video/types';\n\nexport interface VideoState {\n status: VideoStatus;\n /** Воспроизведение запущено, но видео ждёт данные */\n waiting: boolean;\n /** Длительность из метаданных; `null`, пока неизвестна или бесконечна (live) */\n duration: number | null;\n /** Натуральный размер видео из метаданных */\n size: { width: number; height: number } | null;\n /** Звук выключен */\n muted: boolean;\n /** Громкость от 0 до 1 */\n volume: number;\n /** Скорость воспроизведения */\n rate: number;\n /** Видимость контролов: прячутся после бездействия во время воспроизведения */\n controlsVisible: boolean;\n /** Плеер развёрнут на весь экран */\n fullscreen: boolean;\n /** Куда `Video.Controls` переносятся порталом вне fullscreen; `null` — остаются на месте */\n controlsContainer: HTMLElement | null;\n /** Ускорение удержанием: видео играет на 2x, выбранная скорость (`rate`) не меняется */\n boosted: boolean;\n /** Куда переносится индикатор ускорения вне fullscreen; `null` — вверху плеера */\n indicatorContainer: HTMLElement | null;\n}\n\nexport interface VideoTime {\n current: number;\n duration: number;\n /** Конец загруженного фрагмента, в котором находится текущая позиция */\n buffered: number;\n /**\n * Позиция, с которой началось воспроизведение текущего источника. Для live (бесконечная длительность)\n * прошедшее время считается от неё: у live HLS `currentTime` идёт от начала окна плейлиста\n */\n origin: number;\n}\n\nexport interface VideoSourceOptions {\n src?: string;\n sources?: VideoSource[];\n}\n\ntype VideoCallbacks = Pick<VideoProps, 'onPlay' | 'onPause' | 'onEnded' | 'onError'>;\n\nexport interface VideoStoreOptions extends VideoSourceOptions {\n /** Актуальные колбэки и attachMedia читаются в момент события — без пересоздания стора */\n getCallbacks: () => VideoCallbacks & { attachMedia?: VideoAttachMedia };\n}\n\nexport interface VideoStore {\n getState: () => VideoState;\n /** Подписка на изменения состояния (для `useSyncExternalStore`) */\n subscribe: (listener: VoidFunction) => VoidFunction;\n getTime: () => VideoTime;\n /** Подписка на время: каждый кадр во время воспроизведения, минуя React */\n subscribeTime: (listener: (time: VideoTime) => void) => VoidFunction;\n /** Callback ref для `<video>` — единственный способ привязать элемент к стору */\n attach: (element: HTMLVideoElement | null) => void;\n getVideoElement: () => HTMLVideoElement | null;\n /** Смена источника: сбрасывает состояние в `idle` */\n setSource: (source: VideoSourceOptions) => void;\n play: VoidFunction;\n pause: VoidFunction;\n seek: (seconds: number) => void;\n /** Перемотка относительно текущей позиции */\n seekBy: (seconds: number) => void;\n /** Повторная загрузка после ошибки с запуском воспроизведения */\n retry: VoidFunction;\n /** play, если видео на паузе, закончилось или ещё не запускалось; иначе pause */\n toggle: VoidFunction;\n setMuted: (muted: boolean) => void;\n /** Громкость от 0 до 1. Ненулевая громкость включает звук, нулевая — выключает */\n setVolume: (volume: number) => void;\n /** Следующая скорость из ряда 1x → 1.5x → 2x → 1x */\n cycleRate: VoidFunction;\n /** Взаимодействие с плеером: показывает контролы и перезапускает таймер автоскрытия */\n notifyActivity: VoidFunction;\n /** Тап по видео на mobile: показать или спрятать контролы */\n toggleControls: VoidFunction;\n /** Прятать контролы по бездействию и на паузе, а не только во время воспроизведения (mobile) */\n setHideWhenPaused: (hide: boolean) => void;\n /** Пока удержание активно (фокус внутри контролов, перетаскивание ползунка), контролы не прячутся */\n holdControls: (hold: boolean) => void;\n /** Callback ref для корня `Video.Player` — элемента, который разворачивается на весь экран */\n attachRoot: (element: HTMLElement | null) => void;\n getRoot: () => HTMLElement | null;\n toggleFullscreen: VoidFunction;\n /** Контейнер для `Video.Controls` вне fullscreen (например, тулбар вьювера); `null` — контролы на месте */\n setControlsContainer: (element: HTMLElement | null) => void;\n /** Контейнер для индикатора ускорения вне fullscreen (например, под шапкой вьювера); `null` — вверху плеера */\n setIndicatorContainer: (element: HTMLElement | null) => void;\n /**\n * Ускорение удержанием (палец или кнопка мыши на видео): только во время воспроизведения и если скорость ещё\n * не 2x. `hideControls` — спрятать контролы на это время (desktop). Возвращает, включилось ли ускорение\n */\n setBoost: (active: boolean, options?: { hideControls?: boolean }) => boolean;\n}\n\n/** Ряд скоростей воспроизведения */\nexport const PLAYBACK_RATES = [1, 1.5, 2];\n\n/** Скорость ускорения удержанием */\nexport const BOOST_RATE = 2;\n\n/** Задержка автоскрытия контролов по спеке */\nexport const CONTROLS_HIDE_DELAY_MS = 4000;\n\n/** iPhone: Fullscreen API для элементов нет, есть только нативный полноэкранный плеер */\ntype WebkitVideoElement = HTMLVideoElement & { webkitEnterFullscreen?: VoidFunction };\n\nconst INITIAL_STATE: VideoState = {\n status: 'idle',\n waiting: false,\n duration: null,\n size: null,\n muted: false,\n volume: 1,\n rate: 1,\n controlsVisible: true,\n fullscreen: false,\n controlsContainer: null,\n boosted: false,\n indicatorContainer: null,\n};\n\n/** Состояние, которое переживает смену источника: настройки пользователя, fullscreen и место контролов */\nconst pickPreserved = ({\n muted,\n volume,\n rate,\n fullscreen,\n controlsContainer,\n indicatorContainer,\n}: VideoState): Partial<VideoState> => ({\n muted,\n volume,\n rate,\n fullscreen,\n controlsContainer,\n indicatorContainer,\n});\n\nconst getSourceKey = ({ src, sources }: VideoSourceOptions): string =>\n JSON.stringify([src ?? null, sources?.map(({ src, type }) => [src, type ?? null]) ?? null]);\n\n/** Как браузер выбирает `<source>`: первый, тип которого поддерживается (или без типа) */\nconst pickSource = (video: HTMLVideoElement, { src, sources }: VideoSourceOptions): string | undefined => {\n const playable = sources?.find(({ type }) => !type || video.canPlayType(type) !== '');\n return playable?.src ?? src;\n};\n\nconst toDuration = (value: number): number | null => (Number.isFinite(value) && value > 0 ? value : null);\n\nexport const createVideoStore = ({ getCallbacks, ...initialSource }: VideoStoreOptions): VideoStore => {\n let state: VideoState = INITIAL_STATE;\n let source: VideoSourceOptions = initialSource;\n let sourceKey = getSourceKey(initialSource);\n let video: HTMLVideoElement | null = null;\n let detachMedia: VoidFunction | null = null;\n let rafId: number | null = null;\n /** Воспроизведение запускали хотя бы раз для текущего источника */\n let started = false;\n /** Позиция первого playing текущего источника — точка отсчёта для live */\n let origin: number | null = null;\n let root: HTMLElement | null = null;\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n let holds = 0;\n /** Прятать контролы и на паузе (mobile: на паузе по центру видео есть кнопка воспроизведения) */\n let hideWhenPaused = false;\n\n const listeners = new Set<VoidFunction>();\n const timeListeners = new Set<(time: VideoTime) => void>();\n\n const setState = (patch: Partial<VideoState>): void => {\n const keys = Object.keys(patch) as (keyof VideoState)[];\n if (keys.every((key) => patch[key] === state[key])) {\n return;\n }\n state = { ...state, ...patch };\n listeners.forEach((listener) => listener());\n };\n\n const getTime = (): VideoTime => {\n if (!video) {\n return { current: 0, duration: state.duration ?? 0, buffered: 0, origin: origin ?? 0 };\n }\n let buffered = 0;\n for (let i = 0; i < video.buffered.length; i += 1) {\n if (video.buffered.start(i) <= video.currentTime) {\n buffered = Math.max(buffered, video.buffered.end(i));\n }\n }\n return {\n current: video.currentTime,\n duration: toDuration(video.duration) ?? 0,\n buffered,\n origin: origin ?? 0,\n };\n };\n\n const emitTime = (): void => {\n if (timeListeners.size === 0) {\n return;\n }\n const time = getTime();\n timeListeners.forEach((listener) => listener(time));\n };\n\n const stopTicking = (): void => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n };\n\n const tick = (): void => {\n emitTime();\n rafId = requestAnimationFrame(tick);\n };\n\n const startTicking = (): void => {\n if (rafId === null && timeListeners.size > 0) {\n rafId = requestAnimationFrame(tick);\n }\n };\n\n const clearHideTimer = (): void => {\n if (hideTimer !== null) {\n clearTimeout(hideTimer);\n hideTimer = null;\n }\n };\n\n /** Прячем контролы только во время воспроизведения, без удержаний; на паузе и в конце они видны */\n /** Контролы прячутся во время воспроизведения, а с `hideWhenPaused` — и на паузе; после окончания видны */\n const canHide = (): boolean =>\n holds === 0 && (state.status === 'playing' || (hideWhenPaused && state.status === 'paused'));\n\n const scheduleHide = (): void => {\n clearHideTimer();\n if (!canHide()) {\n return;\n }\n hideTimer = setTimeout(() => {\n hideTimer = null;\n if (canHide()) {\n setState({ controlsVisible: false });\n }\n }, CONTROLS_HIDE_DELAY_MS);\n };\n\n const showControls = (): void => {\n setState({ controlsVisible: true });\n scheduleHide();\n };\n\n /** Лоадер — только при первом запуске и повторе; снятие с паузы обходится флагом waiting */\n const enterLoading = (): void => {\n if (state.status === 'idle' || state.status === 'ended') {\n setState({ status: 'loading' });\n }\n };\n\n /** Перемотка назад после окончания: видео больше не закончено — это пауза (play вместо «повторить») */\n const leaveEnded = (): void => {\n if (state.status === 'ended' && video && !video.ended) {\n setState({ status: 'paused' });\n }\n };\n\n /** Ускорение заканчивается вместе с воспроизведением: пауза, конец, ошибка, смена источника */\n const endBoost = (): void => {\n if (!state.boosted) {\n return;\n }\n setState({ boosted: false });\n if (video) {\n video.playbackRate = state.rate;\n }\n };\n\n const fail = (error: unknown): void => {\n endBoost();\n stopTicking();\n clearHideTimer();\n setState({ status: 'error', waiting: false });\n getCallbacks().onError?.(error);\n };\n\n const handlers: Record<string, VoidFunction> = {\n loadedmetadata: () => {\n if (!video) {\n return;\n }\n setState({\n duration: toDuration(video.duration),\n size:\n video.videoWidth && video.videoHeight\n ? { width: video.videoWidth, height: video.videoHeight }\n : null,\n });\n emitTime();\n },\n durationchange: () => {\n video && setState({ duration: toDuration(video.duration) });\n },\n play: () => {\n // воспроизведение могло начаться не через store.play (например, нативно)\n started = true;\n enterLoading();\n getCallbacks().onPlay?.();\n },\n playing: () => {\n if (origin === null && video) {\n origin = video.currentTime;\n }\n const wasPlaying = state.status === 'playing';\n setState({ status: 'playing', waiting: false });\n startTicking();\n if (!wasPlaying) {\n scheduleHide();\n }\n },\n waiting: () => setState({ waiting: true }),\n canplay: () => setState({ waiting: false }),\n pause: () => {\n endBoost();\n stopTicking();\n emitTime();\n // pause приходит и перед ended, и при ошибке — эти состояния главнее\n if (!video || video.ended || state.status === 'error') {\n return;\n }\n setState({ status: started ? 'paused' : 'idle', waiting: false, controlsVisible: true });\n scheduleHide();\n getCallbacks().onPause?.();\n },\n ended: () => {\n endBoost();\n stopTicking();\n emitTime();\n clearHideTimer();\n setState({ status: 'ended', waiting: false, controlsVisible: true });\n getCallbacks().onEnded?.();\n },\n error: () => fail(video?.error ?? new Error('Video loading error')),\n volumechange: () => {\n video && setState({ muted: video.muted, volume: video.volume });\n },\n ratechange: () => {\n // ускорение удержанием — не выбор пользователя: выбранная скорость остаётся прежней\n if (video && !state.boosted) {\n setState({ rate: video.playbackRate });\n }\n },\n webkitbeginfullscreen: () => setState({ fullscreen: true }),\n webkitendfullscreen: () => setState({ fullscreen: false }),\n progress: emitTime,\n seeked: () => {\n leaveEnded();\n emitTime();\n },\n timeupdate: () => {\n // во время воспроизведения время двигает rAF\n if (state.status !== 'playing') {\n emitTime();\n }\n },\n };\n\n const listen = (element: HTMLVideoElement, add: boolean): void => {\n Object.entries(handlers).forEach(([name, handler]) =>\n add ? element.addEventListener(name, handler) : element.removeEventListener(name, handler)\n );\n };\n\n const applySource = (): void => {\n if (!video) {\n return;\n }\n detachMedia?.();\n detachMedia = null;\n const { attachMedia } = getCallbacks();\n if (attachMedia) {\n const element = video;\n detachMedia = attachMedia(element, {\n onError: (error) => {\n // ошибка от уже отключённой библиотеки не должна ломать новый источник\n if (video === element) {\n fail(error);\n }\n },\n });\n return;\n }\n const url = pickSource(video, source);\n if (url) {\n video.src = url;\n } else {\n video.removeAttribute('src');\n }\n video.load();\n };\n\n const resetState = (): void => {\n endBoost();\n stopTicking();\n clearHideTimer();\n started = false;\n origin = null;\n state = { ...INITIAL_STATE, ...pickPreserved(state) };\n listeners.forEach((listener) => listener());\n };\n\n const onFullscreenChange = (): void => {\n setState({ fullscreen: !!root && document.fullscreenElement === root });\n };\n\n const store: VideoStore = {\n getState: () => state,\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getTime,\n subscribeTime: (listener) => {\n timeListeners.add(listener);\n listener(getTime());\n if (state.status === 'playing') {\n startTicking();\n }\n return () => {\n timeListeners.delete(listener);\n if (timeListeners.size === 0) {\n stopTicking();\n }\n };\n },\n attach: (element) => {\n if (video === element) {\n return;\n }\n // ускорение привязано к удержанию на этом элементе: со сменой элемента оно не переживает\n endBoost();\n if (video) {\n listen(video, false);\n detachMedia?.();\n detachMedia = null;\n stopTicking();\n }\n video = element;\n if (!video) {\n return;\n }\n listen(video, true);\n // настройки пользователя переживают смену элемента\n video.muted = state.muted;\n video.volume = state.volume;\n applySource();\n video.playbackRate = state.rate;\n },\n getVideoElement: () => video,\n setSource: (nextSource) => {\n const nextKey = getSourceKey(nextSource);\n if (nextKey === sourceKey) {\n return;\n }\n source = nextSource;\n sourceKey = nextKey;\n resetState();\n applySource();\n },\n play: () => {\n if (!video) {\n return;\n }\n started = true;\n enterLoading();\n if (video.ended) {\n video.currentTime = 0;\n }\n const element = video;\n // play() может быть отклонён (политика autoplay, источник не загрузился)\n // в старых браузерах может вернуть не Promise, а undefined\n Promise.resolve(element.play()).catch(() => {\n if (video !== element || state.status === 'error' || !element.paused) {\n return;\n }\n if (state.status === 'loading') {\n started = element.currentTime > 0;\n setState({ status: started ? 'paused' : 'idle', waiting: false });\n }\n });\n },\n pause: () => {\n video?.pause();\n },\n seek: (seconds) => {\n if (!video) {\n return;\n }\n const duration = toDuration(video.duration);\n video.currentTime = Math.max(0, duration === null ? seconds : Math.min(seconds, duration));\n leaveEnded();\n emitTime();\n },\n seekBy: (seconds) => {\n if (video) {\n store.seek(video.currentTime + seconds);\n }\n },\n retry: () => {\n if (!video) {\n return;\n }\n resetState();\n applySource();\n store.play();\n },\n toggle: () => {\n if (!video) {\n return;\n }\n if (state.status === 'playing' || (state.status === 'loading' && !video.paused)) {\n video.pause();\n return;\n }\n store.play();\n },\n setMuted: (muted) => {\n if (video) {\n video.muted = muted;\n }\n },\n setVolume: (volume) => {\n if (!video) {\n return;\n }\n const next = Math.min(Math.max(volume, 0), 1);\n video.volume = next;\n video.muted = next === 0;\n },\n cycleRate: () => {\n if (!video) {\n return;\n }\n const index = PLAYBACK_RATES.indexOf(state.rate);\n video.playbackRate = PLAYBACK_RATES[(index + 1) % PLAYBACK_RATES.length];\n },\n notifyActivity: showControls,\n toggleControls: () => {\n if (state.controlsVisible && canHide()) {\n clearHideTimer();\n setState({ controlsVisible: false });\n return;\n }\n showControls();\n },\n setHideWhenPaused: (hide) => {\n hideWhenPaused = hide;\n if (state.controlsVisible) {\n scheduleHide();\n }\n },\n holdControls: (hold) => {\n holds = Math.max(0, holds + (hold ? 1 : -1));\n if (holds > 0) {\n clearHideTimer();\n setState({ controlsVisible: true });\n } else {\n scheduleHide();\n }\n },\n attachRoot: (element) => {\n if (root === element) {\n return;\n }\n if (root) {\n document.removeEventListener('fullscreenchange', onFullscreenChange);\n if (document.fullscreenElement === root) {\n void document.exitFullscreen();\n }\n }\n root = element;\n if (root) {\n document.addEventListener('fullscreenchange', onFullscreenChange);\n } else {\n clearHideTimer();\n }\n },\n getRoot: () => root,\n toggleFullscreen: () => {\n if (root && document.fullscreenElement === root) {\n void document.exitFullscreen();\n return;\n }\n if (root && document.fullscreenEnabled && typeof root.requestFullscreen === 'function') {\n root.requestFullscreen().catch(() => {});\n return;\n }\n // iPhone: нативный плеер\n const webkitVideo: WebkitVideoElement | null = video;\n webkitVideo?.webkitEnterFullscreen?.();\n },\n setControlsContainer: (element) => setState({ controlsContainer: element }),\n setIndicatorContainer: (element) => setState({ indicatorContainer: element }),\n setBoost: (active, { hideControls = false } = {}) => {\n if (!active) {\n endBoost();\n return false;\n }\n if (!video || state.boosted || state.status !== 'playing' || state.rate === BOOST_RATE) {\n return false;\n }\n if (hideControls) {\n clearHideTimer();\n setState({ boosted: true, controlsVisible: false });\n } else {\n setState({ boosted: true });\n }\n video.playbackRate = BOOST_RATE;\n return true;\n },\n };\n\n return store;\n};\n"],"names":["src"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"store.js","sources":["src/internal/store.ts"],"sourcesContent":["import {\n type VideoAttachMedia,\n type VideoProps,\n type VideoSource,\n type VideoStatus,\n} from '@hh.ru/magritte-ui-video/types';\n\nexport interface VideoState {\n status: VideoStatus;\n /** Воспроизведение запущено, но видео ждёт данные */\n waiting: boolean;\n /**\n * Повторная попытка после ошибки: до начала воспроизведения видео и превью не показываются — лоадер на тёмном\n * фоне, а не мелькание превью перед новой ошибкой\n */\n retrying: boolean;\n /** Длительность из метаданных; `null`, пока неизвестна или бесконечна (live) */\n duration: number | null;\n /** Натуральный размер видео из метаданных */\n size: { width: number; height: number } | null;\n /** Звук выключен */\n muted: boolean;\n /** Громкость от 0 до 1 */\n volume: number;\n /** Скорость воспроизведения */\n rate: number;\n /** Видимость контролов: прячутся после бездействия во время воспроизведения */\n controlsVisible: boolean;\n /** Плеер развёрнут на весь экран */\n fullscreen: boolean;\n /** Куда `Video.Controls` переносятся порталом вне fullscreen; `null` — остаются на месте */\n controlsContainer: HTMLElement | null;\n /** Ускорение удержанием: видео играет на 2x, выбранная скорость (`rate`) не меняется */\n boosted: boolean;\n /** Куда переносится индикатор ускорения вне fullscreen; `null` — вверху плеера */\n indicatorContainer: HTMLElement | null;\n}\n\n/**\n * Исключение из правил владельца видимости контролов: `shown` — показать и не прятать (фокус с клавиатуры в контролах,\n * перетаскивание бегунка), `hidden` — спрятать и не показывать от активности (ускорение удержанием на desktop),\n * `null` — исключений нет\n */\nexport type VideoControlsPin = 'shown' | 'hidden' | null;\n\n/**\n * Внешний владелец видимости контролов (тулбары вьювера медиа). Пока он подключён, контролы показываются и прячутся\n * только по нему: собственного таймера у плеера нет, активность и тапы по видео передаются ему\n */\nexport interface VideoControlsVisibilityHost {\n isVisible: () => boolean;\n subscribe: (listener: (visible: boolean) => void) => VoidFunction;\n /** Активность пользователя в плеере: движение мыши, нажатия, горячие клавиши */\n notifyActivity: VoidFunction;\n /** Тап по видео (mobile) */\n toggle: VoidFunction;\n setPin: (pin: VideoControlsPin) => void;\n}\n\nexport interface VideoTime {\n current: number;\n duration: number;\n /** Конец загруженного фрагмента, в котором находится текущая позиция */\n buffered: number;\n /**\n * Позиция, с которой началось воспроизведение текущего источника. Для live (бесконечная длительность)\n * прошедшее время считается от неё: у live HLS `currentTime` идёт от начала окна плейлиста\n */\n origin: number;\n}\n\nexport interface VideoSourceOptions {\n src?: string;\n sources?: VideoSource[];\n}\n\ntype VideoCallbacks = Pick<VideoProps, 'onPlay' | 'onPause' | 'onEnded' | 'onError'>;\n\n/** Режимы воспроизведения из пропсов `Video`; `interactive={false}` включает autoPlay и loop */\nexport interface VideoPlaybackOptions {\n autoPlay: boolean;\n autoPause: boolean;\n loop: boolean;\n interactive: boolean;\n}\n\nexport interface VideoStoreOptions extends VideoSourceOptions {\n /** Актуальные колбэки и attachMedia читаются в момент события — без пересоздания стора */\n getCallbacks: () => VideoCallbacks & { attachMedia?: VideoAttachMedia };\n /** Актуальные режимы воспроизведения; после их смены стор надо уведомить через `syncOptions` */\n getOptions: () => VideoPlaybackOptions;\n /** Звук и громкость на старте */\n defaultMuted?: boolean;\n defaultVolume?: number;\n}\n\nexport interface VideoStore {\n getState: () => VideoState;\n /** Подписка на изменения состояния (для `useSyncExternalStore`) */\n subscribe: (listener: VoidFunction) => VoidFunction;\n getTime: () => VideoTime;\n /** Подписка на время: каждый кадр во время воспроизведения, минуя React */\n subscribeTime: (listener: (time: VideoTime) => void) => VoidFunction;\n /** Callback ref для `<video>` — единственный способ привязать элемент к стору */\n attach: (element: HTMLVideoElement | null) => void;\n getVideoElement: () => HTMLVideoElement | null;\n /** Смена источника: сбрасывает состояние в `idle` */\n setSource: (source: VideoSourceOptions) => void;\n play: VoidFunction;\n pause: VoidFunction;\n seek: (seconds: number) => void;\n /** Перемотка относительно текущей позиции */\n seekBy: (seconds: number) => void;\n /**\n * Видимость плеера во вьюпорте (видно не меньше 10%): по ней работают автовоспроизведение и автопауза.\n * `null` — неизвестно (плеер размонтирован)\n */\n setVisible: (visible: boolean | null) => void;\n /** Режимы воспроизведения из пропсов изменились */\n syncOptions: VoidFunction;\n /** Повторная загрузка после ошибки с запуском воспроизведения */\n retry: VoidFunction;\n /** play, если видео на паузе, закончилось или ещё не запускалось; иначе pause */\n toggle: VoidFunction;\n setMuted: (muted: boolean) => void;\n /** Громкость от 0 до 1. Ненулевая громкость включает звук, нулевая — выключает */\n setVolume: (volume: number) => void;\n /** Следующая скорость из ряда 1x → 1.5x → 2x → 1x */\n cycleRate: VoidFunction;\n /** Взаимодействие с плеером: показывает контролы и перезапускает таймер автоскрытия */\n notifyActivity: VoidFunction;\n /** Тап по видео на mobile: показать или спрятать контролы */\n toggleControls: VoidFunction;\n /** Прятать контролы по бездействию и на паузе, а не только во время воспроизведения (mobile) */\n setHideWhenPaused: (hide: boolean) => void;\n /** Пока удержание активно (фокус внутри контролов, перетаскивание ползунка), контролы не прячутся */\n holdControls: (hold: boolean) => void;\n /** Подключить внешнего владельца видимости контролов; `null` — плеер снова управляет ими сам */\n setControlsVisibilityHost: (host: VideoControlsVisibilityHost | null) => void;\n /** Callback ref для корня `Video.Player` — элемента, который разворачивается на весь экран */\n attachRoot: (element: HTMLElement | null) => void;\n getRoot: () => HTMLElement | null;\n toggleFullscreen: VoidFunction;\n /** Контейнер для `Video.Controls` вне fullscreen (например, тулбар вьювера); `null` — контролы на месте */\n setControlsContainer: (element: HTMLElement | null) => void;\n /** Контейнер для индикатора ускорения вне fullscreen (например, под шапкой вьювера); `null` — вверху плеера */\n setIndicatorContainer: (element: HTMLElement | null) => void;\n /**\n * Ускорение удержанием (палец или кнопка мыши на видео): только во время воспроизведения и если скорость ещё\n * не 2x. `hideControls` — спрятать контролы на это время (desktop). Возвращает, включилось ли ускорение\n */\n setBoost: (active: boolean, options?: { hideControls?: boolean }) => boolean;\n}\n\n/** Ряд скоростей воспроизведения */\nexport const PLAYBACK_RATES = [1, 1.5, 2];\n\n/**\n * Событие на document: видео начало играть со звуком — остальные видео со звуком встают на паузу.\n * Через document, а не общий модуль: работает и между разными копиями пакета на странице\n */\nconst AUDIBLE_EVENT = 'magritte-video-audible';\n\n/** Скорость ускорения удержанием */\nexport const BOOST_RATE = 2;\n\n/** Задержка автоскрытия контролов по спеке */\nexport const CONTROLS_HIDE_DELAY_MS = 4000;\n\n/** iPhone: Fullscreen API для элементов нет, есть только нативный полноэкранный плеер */\ntype WebkitVideoElement = HTMLVideoElement & { webkitEnterFullscreen?: VoidFunction };\n\nconst INITIAL_STATE: VideoState = {\n status: 'idle',\n waiting: false,\n retrying: false,\n duration: null,\n size: null,\n muted: false,\n volume: 1,\n rate: 1,\n controlsVisible: true,\n fullscreen: false,\n controlsContainer: null,\n boosted: false,\n indicatorContainer: null,\n};\n\n/** Состояние, которое переживает смену источника: настройки пользователя, fullscreen и место контролов */\nconst pickPreserved = ({\n muted,\n volume,\n rate,\n fullscreen,\n controlsContainer,\n indicatorContainer,\n}: VideoState): Partial<VideoState> => ({\n muted,\n volume,\n rate,\n fullscreen,\n controlsContainer,\n indicatorContainer,\n});\n\nconst getSourceKey = ({ src, sources }: VideoSourceOptions): string =>\n JSON.stringify([src ?? null, sources?.map(({ src, type }) => [src, type ?? null]) ?? null]);\n\n/** Как браузер выбирает `<source>`: первый, тип которого поддерживается (или без типа) */\nconst pickSource = (video: HTMLVideoElement, { src, sources }: VideoSourceOptions): string | undefined => {\n const playable = sources?.find(({ type }) => !type || video.canPlayType(type) !== '');\n return playable?.src ?? src;\n};\n\nconst toDuration = (value: number): number | null => (Number.isFinite(value) && value > 0 ? value : null);\n\nconst clampVolume = (volume: number): number => Math.min(Math.max(volume, 0), 1);\n\nexport const createVideoStore = ({\n getCallbacks,\n getOptions,\n defaultMuted = false,\n defaultVolume = 1,\n ...initialSource\n}: VideoStoreOptions): VideoStore => {\n const isAutoPlay = (): boolean => {\n const { autoPlay, interactive } = getOptions();\n return autoPlay || !interactive;\n };\n\n let state: VideoState = {\n ...INITIAL_STATE,\n // автовоспроизведение и неинтерактивный режим — без звука\n muted: defaultMuted || isAutoPlay(),\n volume: Number.isFinite(defaultVolume) ? clampVolume(defaultVolume) : 1,\n };\n let source: VideoSourceOptions = initialSource;\n let sourceKey = getSourceKey(initialSource);\n let video: HTMLVideoElement | null = null;\n let detachMedia: VoidFunction | null = null;\n let rafId: number | null = null;\n /** Воспроизведение запускали хотя бы раз для текущего источника */\n let started = false;\n /** Позиция первого playing текущего источника — точка отсчёта для live */\n let origin: number | null = null;\n let root: HTMLElement | null = null;\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n let holds = 0;\n /** Прятать контролы и на паузе (mobile: на паузе по центру видео есть кнопка воспроизведения) */\n let hideWhenPaused = false;\n /** Внешний владелец видимости контролов */\n let host: VideoControlsVisibilityHost | null = null;\n let unsubscribeHost: VoidFunction | null = null;\n /** Последнее исключение, переданное владельцу */\n let hostPin: VideoControlsPin = null;\n /** Ускорение прячет контролы (desktop) */\n let boostHidesControls = false;\n /** Видимость во вьюпорте; `null` — неизвестна */\n let visible: boolean | null = null;\n /** Видео поставила на паузу автопауза, а не пользователь: автовоспроизведение может его продолжить */\n let pausedByViewport = false;\n /** Пользователь сам менял звук: автовоспроизведение больше его не выключает */\n let soundChangedByUser = false;\n /** Маркер своего события AUDIBLE_EVENT */\n const audibleToken = {};\n\n const listeners = new Set<VoidFunction>();\n const timeListeners = new Set<(time: VideoTime) => void>();\n\n const getControlsPin = (): VideoControlsPin => {\n if (state.boosted && boostHidesControls) {\n return 'hidden';\n }\n return holds > 0 ? 'shown' : null;\n };\n\n /** Передаёт владельцу видимости исключение, если оно изменилось */\n const syncControlsPin = (): void => {\n const pin = getControlsPin();\n if (host && pin !== hostPin) {\n hostPin = pin;\n host.setPin(pin);\n }\n };\n\n const setState = (patch: Partial<VideoState>): void => {\n const keys = Object.keys(patch) as (keyof VideoState)[];\n if (keys.every((key) => patch[key] === state[key])) {\n return;\n }\n state = { ...state, ...patch };\n listeners.forEach((listener) => listener());\n syncControlsPin();\n };\n\n const getTime = (): VideoTime => {\n if (!video) {\n return { current: 0, duration: state.duration ?? 0, buffered: 0, origin: origin ?? 0 };\n }\n let buffered = 0;\n for (let i = 0; i < video.buffered.length; i += 1) {\n if (video.buffered.start(i) <= video.currentTime) {\n buffered = Math.max(buffered, video.buffered.end(i));\n }\n }\n return {\n current: video.currentTime,\n duration: toDuration(video.duration) ?? 0,\n buffered,\n origin: origin ?? 0,\n };\n };\n\n const emitTime = (): void => {\n if (timeListeners.size === 0) {\n return;\n }\n const time = getTime();\n timeListeners.forEach((listener) => listener(time));\n };\n\n const stopTicking = (): void => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n };\n\n const tick = (): void => {\n emitTime();\n rafId = requestAnimationFrame(tick);\n };\n\n const startTicking = (): void => {\n if (rafId === null && timeListeners.size > 0) {\n rafId = requestAnimationFrame(tick);\n }\n };\n\n const clearHideTimer = (): void => {\n if (hideTimer !== null) {\n clearTimeout(hideTimer);\n hideTimer = null;\n }\n };\n\n /** Контролы прячутся во время воспроизведения, а с `hideWhenPaused` — и на паузе; после окончания видны */\n const canHide = (): boolean =>\n holds === 0 && (state.status === 'playing' || (hideWhenPaused && state.status === 'paused'));\n\n const scheduleHide = (): void => {\n clearHideTimer();\n // с внешним владельцем видимости своего таймера нет\n if (host || !canHide()) {\n return;\n }\n hideTimer = setTimeout(() => {\n hideTimer = null;\n if (canHide()) {\n setState({ controlsVisible: false });\n }\n }, CONTROLS_HIDE_DELAY_MS);\n };\n\n const showControls = (): void => {\n if (host) {\n host.notifyActivity();\n return;\n }\n setState({ controlsVisible: true });\n scheduleHide();\n };\n\n /** Лоадер — только при первом запуске и повторе; снятие с паузы обходится флагом waiting */\n const enterLoading = (): void => {\n if (state.status === 'idle' || state.status === 'ended') {\n setState({ status: 'loading' });\n }\n };\n\n /** Перемотка назад после окончания: видео больше не закончено — это пауза (play вместо «повторить») */\n const leaveEnded = (): void => {\n if (state.status === 'ended' && video && !video.ended) {\n setState({ status: 'paused' });\n }\n };\n\n /** Ускорение заканчивается вместе с воспроизведением: пауза, конец, ошибка, смена источника */\n const endBoost = (): void => {\n if (!state.boosted) {\n return;\n }\n boostHidesControls = false;\n setState({ boosted: false });\n if (video) {\n video.playbackRate = state.rate;\n }\n };\n\n const fail = (error: unknown): void => {\n endBoost();\n stopTicking();\n clearHideTimer();\n setState({ status: 'error', waiting: false, retrying: false });\n getCallbacks().onError?.(error);\n };\n\n const isAudible = (): boolean => !!video && !video.paused && !video.muted && video.volume > 0;\n\n /** Видео играет со звуком — остальные видео со звуком встают на паузу */\n const claimAudio = (): void => {\n if (isAudible()) {\n document.dispatchEvent(new CustomEvent(AUDIBLE_EVENT, { detail: audibleToken }));\n }\n };\n\n const onAudibleElsewhere = (event: Event): void => {\n if ((event as CustomEvent).detail !== audibleToken && isAudible()) {\n video?.pause();\n }\n };\n\n const play = (): void => {\n if (!video) {\n return;\n }\n pausedByViewport = false;\n started = true;\n enterLoading();\n if (video.ended) {\n video.currentTime = 0;\n }\n const element = video;\n // play() может быть отклонён (политика autoplay, источник не загрузился)\n // в старых браузерах может вернуть не Promise, а undefined\n Promise.resolve(element.play()).catch(() => {\n if (video !== element || state.status === 'error' || !element.paused) {\n return;\n }\n if (state.status === 'loading') {\n started = element.currentTime > 0;\n setState({ status: started ? 'paused' : 'idle', waiting: false, retrying: false });\n }\n });\n };\n\n /** Автовоспроизведение: видео ещё не запускали или его остановила автопауза, и плеер во вьюпорте */\n const tryAutoPlay = (): void => {\n // видимость сообщает Video.Player; пока она неизвестна, не запускаем — плеер может быть за пределами экрана\n if (!video || visible !== true || !isAutoPlay()) {\n return;\n }\n if (state.status !== 'idle' && !(state.status === 'paused' && pausedByViewport)) {\n return;\n }\n pausedByViewport = false;\n // звук выключен, пока пользователь не включит его сам; неинтерактивное видео — всегда без звука\n if (!soundChangedByUser || !getOptions().interactive) {\n video.muted = true;\n }\n play();\n };\n\n const autoPause = (): void => {\n if (!video || !getOptions().autoPause || video.paused) {\n return;\n }\n video.pause();\n pausedByViewport = true;\n };\n\n const handlers: Record<string, VoidFunction> = {\n loadedmetadata: () => {\n if (!video) {\n return;\n }\n setState({\n duration: toDuration(video.duration),\n size:\n video.videoWidth && video.videoHeight\n ? { width: video.videoWidth, height: video.videoHeight }\n : null,\n });\n emitTime();\n },\n durationchange: () => {\n video && setState({ duration: toDuration(video.duration) });\n },\n play: () => {\n // воспроизведение могло начаться не через store.play (например, нативно)\n started = true;\n enterLoading();\n claimAudio();\n getCallbacks().onPlay?.();\n },\n playing: () => {\n if (origin === null && video) {\n origin = video.currentTime;\n }\n const wasPlaying = state.status === 'playing';\n setState({ status: 'playing', waiting: false, retrying: false });\n startTicking();\n if (!wasPlaying) {\n scheduleHide();\n }\n },\n waiting: () => setState({ waiting: true }),\n canplay: () => setState({ waiting: false }),\n pause: () => {\n endBoost();\n stopTicking();\n emitTime();\n // pause приходит и перед ended, и при ошибке — эти состояния главнее\n if (!video || video.ended || state.status === 'error') {\n return;\n }\n setState({ status: started ? 'paused' : 'idle', waiting: false, retrying: false });\n showControls();\n getCallbacks().onPause?.();\n },\n ended: () => {\n endBoost();\n stopTicking();\n emitTime();\n clearHideTimer();\n setState({ status: 'ended', waiting: false });\n // с внешним владельцем видимость — по его правилам\n if (!host) {\n setState({ controlsVisible: true });\n }\n getCallbacks().onEnded?.();\n },\n error: () => fail(video?.error ?? new Error('Video loading error')),\n volumechange: () => {\n if (video) {\n setState({ muted: video.muted, volume: video.volume });\n claimAudio();\n }\n },\n ratechange: () => {\n // ускорение удержанием — не выбор пользователя: выбранная скорость остаётся прежней\n if (video && !state.boosted) {\n setState({ rate: video.playbackRate });\n }\n },\n webkitbeginfullscreen: () => setState({ fullscreen: true }),\n webkitendfullscreen: () => setState({ fullscreen: false }),\n progress: emitTime,\n seeked: () => {\n leaveEnded();\n emitTime();\n },\n timeupdate: () => {\n // во время воспроизведения время двигает rAF\n if (state.status !== 'playing') {\n emitTime();\n }\n },\n };\n\n const listen = (element: HTMLVideoElement, add: boolean): void => {\n Object.entries(handlers).forEach(([name, handler]) =>\n add ? element.addEventListener(name, handler) : element.removeEventListener(name, handler)\n );\n };\n\n /** Загрузка источника молча сбрасывает скорость элемента к `defaultPlaybackRate`: выбранная скорость переживает её */\n const restoreRate = (): void => {\n if (video) {\n video.playbackRate = state.rate;\n }\n };\n\n const applySource = (): void => {\n if (!video) {\n return;\n }\n detachMedia?.();\n detachMedia = null;\n const { attachMedia } = getCallbacks();\n if (attachMedia) {\n const element = video;\n detachMedia = attachMedia(element, {\n onError: (error) => {\n // ошибка от уже отключённой библиотеки не должна ломать новый источник\n if (video === element) {\n fail(error);\n }\n },\n });\n restoreRate();\n return;\n }\n const url = pickSource(video, source);\n if (url) {\n video.src = url;\n } else {\n video.removeAttribute('src');\n }\n video.load();\n restoreRate();\n };\n\n const resetState = (): void => {\n endBoost();\n stopTicking();\n clearHideTimer();\n started = false;\n origin = null;\n pausedByViewport = false;\n state = { ...INITIAL_STATE, ...pickPreserved(state) };\n listeners.forEach((listener) => listener());\n };\n\n const onFullscreenChange = (): void => {\n setState({ fullscreen: !!root && document.fullscreenElement === root });\n };\n\n const store: VideoStore = {\n getState: () => state,\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getTime,\n subscribeTime: (listener) => {\n timeListeners.add(listener);\n listener(getTime());\n if (state.status === 'playing') {\n startTicking();\n }\n return () => {\n timeListeners.delete(listener);\n if (timeListeners.size === 0) {\n stopTicking();\n }\n };\n },\n attach: (element) => {\n if (video === element) {\n return;\n }\n // ускорение привязано к удержанию на этом элементе: со сменой элемента оно не переживает\n endBoost();\n if (video) {\n listen(video, false);\n document.removeEventListener(AUDIBLE_EVENT, onAudibleElsewhere);\n detachMedia?.();\n detachMedia = null;\n stopTicking();\n }\n video = element;\n if (!video) {\n return;\n }\n listen(video, true);\n document.addEventListener(AUDIBLE_EVENT, onAudibleElsewhere);\n // настройки пользователя переживают смену элемента. Значения берём до присваивания: volumechange\n // от первого из них обновляет стор значениями элемента\n const { muted, volume } = state;\n video.muted = muted;\n video.volume = volume;\n video.loop = getOptions().loop || !getOptions().interactive;\n applySource();\n tryAutoPlay();\n },\n getVideoElement: () => video,\n setSource: (nextSource) => {\n const nextKey = getSourceKey(nextSource);\n if (nextKey === sourceKey) {\n return;\n }\n source = nextSource;\n sourceKey = nextKey;\n resetState();\n applySource();\n tryAutoPlay();\n },\n play,\n pause: () => {\n pausedByViewport = false;\n video?.pause();\n },\n seek: (seconds) => {\n if (!video) {\n return;\n }\n const duration = toDuration(video.duration);\n video.currentTime = Math.max(0, duration === null ? seconds : Math.min(seconds, duration));\n leaveEnded();\n emitTime();\n },\n seekBy: (seconds) => {\n if (video) {\n store.seek(video.currentTime + seconds);\n }\n },\n setVisible: (nextVisible) => {\n if (visible === nextVisible) {\n return;\n }\n visible = nextVisible;\n if (visible) {\n tryAutoPlay();\n } else if (visible === false) {\n autoPause();\n }\n },\n syncOptions: () => {\n if (!video) {\n return;\n }\n const { loop, interactive } = getOptions();\n video.loop = loop || !interactive;\n if (!interactive) {\n video.muted = true;\n }\n tryAutoPlay();\n },\n retry: () => {\n if (!video) {\n return;\n }\n resetState();\n setState({ retrying: true });\n applySource();\n store.play();\n },\n toggle: () => {\n if (!video) {\n return;\n }\n if (state.status === 'playing' || (state.status === 'loading' && !video.paused)) {\n store.pause();\n return;\n }\n store.play();\n },\n setMuted: (muted) => {\n if (video) {\n soundChangedByUser = true;\n video.muted = muted;\n }\n },\n setVolume: (volume) => {\n if (!video) {\n return;\n }\n soundChangedByUser = true;\n const next = clampVolume(volume);\n video.volume = next;\n video.muted = next === 0;\n },\n cycleRate: () => {\n if (!video) {\n return;\n }\n const index = PLAYBACK_RATES.indexOf(state.rate);\n video.playbackRate = PLAYBACK_RATES[(index + 1) % PLAYBACK_RATES.length];\n },\n notifyActivity: showControls,\n toggleControls: () => {\n if (host) {\n host.toggle();\n return;\n }\n if (state.controlsVisible && canHide()) {\n clearHideTimer();\n setState({ controlsVisible: false });\n return;\n }\n showControls();\n },\n setHideWhenPaused: (hide) => {\n hideWhenPaused = hide;\n if (state.controlsVisible) {\n scheduleHide();\n }\n },\n holdControls: (hold) => {\n holds = Math.max(0, holds + (hold ? 1 : -1));\n if (host) {\n syncControlsPin();\n return;\n }\n if (holds > 0) {\n clearHideTimer();\n setState({ controlsVisible: true });\n } else {\n scheduleHide();\n }\n },\n setControlsVisibilityHost: (nextHost) => {\n if (host === nextHost) {\n return;\n }\n unsubscribeHost?.();\n unsubscribeHost = null;\n if (host && hostPin !== null) {\n host.setPin(null);\n }\n hostPin = null;\n host = nextHost;\n clearHideTimer();\n if (!host) {\n showControls();\n return;\n }\n unsubscribeHost = host.subscribe((visible) => setState({ controlsVisible: visible }));\n setState({ controlsVisible: host.isVisible() });\n syncControlsPin();\n },\n attachRoot: (element) => {\n if (root === element) {\n return;\n }\n if (root) {\n document.removeEventListener('fullscreenchange', onFullscreenChange);\n if (document.fullscreenElement === root) {\n void document.exitFullscreen();\n }\n }\n root = element;\n if (root) {\n document.addEventListener('fullscreenchange', onFullscreenChange);\n } else {\n clearHideTimer();\n }\n },\n getRoot: () => root,\n toggleFullscreen: () => {\n if (root && document.fullscreenElement === root) {\n void document.exitFullscreen();\n return;\n }\n if (root && document.fullscreenEnabled && typeof root.requestFullscreen === 'function') {\n root.requestFullscreen().catch(() => {});\n return;\n }\n // iPhone: нативный плеер\n const webkitVideo: WebkitVideoElement | null = video;\n webkitVideo?.webkitEnterFullscreen?.();\n },\n setControlsContainer: (element) => setState({ controlsContainer: element }),\n setIndicatorContainer: (element) => setState({ indicatorContainer: element }),\n setBoost: (active, { hideControls = false } = {}) => {\n if (!active) {\n endBoost();\n return false;\n }\n if (!video || state.boosted || state.status !== 'playing' || state.rate === BOOST_RATE) {\n return false;\n }\n if (hideControls) {\n clearHideTimer();\n boostHidesControls = true;\n setState(host ? { boosted: true } : { boosted: true, controlsVisible: false });\n } else {\n setState({ boosted: true });\n }\n video.playbackRate = BOOST_RATE;\n return true;\n },\n };\n\n return store;\n};\n"],"names":["src","visible"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import { type VideoStore } from '../internal/store';
|
|
3
|
+
/** Плеер считается видимым, когда во вьюпорт попала эта доля его площади */
|
|
4
|
+
export declare const VISIBLE_RATIO = 0.1;
|
|
5
|
+
/** Сообщает стору видимость плеера во вьюпорте — по ней работают автовоспроизведение и автопауза */
|
|
6
|
+
export declare const useViewportVisibility: (ref: RefObject<HTMLElement>, store: VideoStore, enabled: boolean) => void;
|