@nikelroot/video-player 0.3.0 → 0.3.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/README.md +38 -0
- package/dist/index.cjs +50 -21
- package/dist/index.js +50 -21
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -8,6 +8,44 @@ Standalone React video player with HLS support, retry/recovery behavior, fullscr
|
|
|
8
8
|
npm install @nikelroot/video-player
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## GitLab CI and automatic npm releases
|
|
12
|
+
|
|
13
|
+
The repository is hosted at https://gitlab.nikelroot.ru/home/nvideoplayer.
|
|
14
|
+
Every push to the default branch runs validation and publishes a new public
|
|
15
|
+
version of `@nikelroot/video-player` to npmjs.com. Merge requests and other
|
|
16
|
+
branches only run validation. Tag pipelines are disabled.
|
|
17
|
+
|
|
18
|
+
The release chooses the highest stable version from `package.json` and npm,
|
|
19
|
+
then increases its patch number (for example, `0.3.2` → `0.3.3`) inside the
|
|
20
|
+
CI workspace, builds the package, and publishes it directly to npm. The source
|
|
21
|
+
repository is not modified: CI does not push commits or create Git tags.
|
|
22
|
+
The published version is visible on npmjs.com; `package.json` in Git remains
|
|
23
|
+
the starting version. Releases are serialized to avoid version collisions.
|
|
24
|
+
The npm package records the source commit as `gitHead`; retrying a job for an
|
|
25
|
+
already-published commit skips publication. If publishing failed before the
|
|
26
|
+
version reached npm, retry the failed `publish` job to calculate the next
|
|
27
|
+
available version and publish again.
|
|
28
|
+
|
|
29
|
+
One-time setup in GitLab:
|
|
30
|
+
|
|
31
|
+
1. Configure a Docker-compatible runner capable of using `node:24-bookworm`.
|
|
32
|
+
2. Protect the default branch (usually `main`).
|
|
33
|
+
3. In **Settings → CI/CD → Variables**, add this **Masked** and **Protected**
|
|
34
|
+
variable with variable expansion disabled:
|
|
35
|
+
- `NPM_TOKEN`: an npm granular access token with read/write permission for
|
|
36
|
+
`@nikelroot/video-player` and **Bypass two-factor authentication** enabled.
|
|
37
|
+
The package publishing settings must permit token publishing. Renew the
|
|
38
|
+
token before its expiration.
|
|
39
|
+
4. Push the repository and CI configuration to GitLab. Do not add secrets to Git.
|
|
40
|
+
|
|
41
|
+
Only `NPM_TOKEN` is required. No GitLab push token or job-token push permission
|
|
42
|
+
is needed.
|
|
43
|
+
|
|
44
|
+
This self-hosted GitLab uses token authentication because npm trusted publishing
|
|
45
|
+
currently supports GitLab.com shared runners only. See the
|
|
46
|
+
[npm CI token guide](https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow/)
|
|
47
|
+
and [trusted publishing documentation](https://docs.npmjs.com/trusted-publishers/).
|
|
48
|
+
|
|
11
49
|
Peer dependencies:
|
|
12
50
|
|
|
13
51
|
```bash
|
package/dist/index.cjs
CHANGED
|
@@ -44,8 +44,9 @@ var import_react = require("react");
|
|
|
44
44
|
function useAudioFallback(options) {
|
|
45
45
|
const latest = (0, import_react.useRef)(options);
|
|
46
46
|
latest.current = options;
|
|
47
|
-
const [videoOnly, setVideoOnly] = (0, import_react.useState)(
|
|
48
|
-
const mode = (0, import_react.useRef)(
|
|
47
|
+
const [videoOnly, setVideoOnly] = (0, import_react.useState)(Boolean(options.fallback));
|
|
48
|
+
const mode = (0, import_react.useRef)(Boolean(options.fallback));
|
|
49
|
+
const progress = (0, import_react.useRef)({ time: 0, at: Date.now(), failed: false });
|
|
49
50
|
const cooldown = (0, import_react.useRef)(0);
|
|
50
51
|
const audioErrors = (0, import_react.useRef)(0);
|
|
51
52
|
const audioErrorTimer = (0, import_react.useRef)(null);
|
|
@@ -62,6 +63,7 @@ function useAudioFallback(options) {
|
|
|
62
63
|
muted: element.muted
|
|
63
64
|
};
|
|
64
65
|
mode.current = next;
|
|
66
|
+
progress.current = { time: element.currentTime, at: Date.now(), failed: false };
|
|
65
67
|
audioErrors.current = 0;
|
|
66
68
|
if (audioErrorTimer.current) clearTimeout(audioErrorTimer.current);
|
|
67
69
|
audioErrorTimer.current = null;
|
|
@@ -71,15 +73,10 @@ function useAudioFallback(options) {
|
|
|
71
73
|
return true;
|
|
72
74
|
}, []);
|
|
73
75
|
const onAudioError = (0, import_react.useCallback)((data) => {
|
|
74
|
-
var _a, _b
|
|
76
|
+
var _a, _b;
|
|
75
77
|
if (!latest.current.fallback || mode.current) return false;
|
|
76
78
|
const isAudio = ((_a = data == null ? void 0 : data.frag) == null ? void 0 : _a.type) === "audio" || (data == null ? void 0 : data.parent) === "audio" || ((_b = data == null ? void 0 : data.context) == null ? void 0 : _b.type) === "audioTrack" || /^audioTrack/.test((data == null ? void 0 : data.details) || "");
|
|
77
79
|
if (!isAudio) return false;
|
|
78
|
-
if ((data == null ? void 0 : data.details) === "fragGap" && ((_c = latest.current.ranges) == null ? void 0 : _c.some((range) => {
|
|
79
|
-
var _a2, _b2;
|
|
80
|
-
const time = (_b2 = (_a2 = latest.current.video.current) == null ? void 0 : _a2.currentTime) != null ? _b2 : 0;
|
|
81
|
-
return time >= range.start - 0.05 && time < range.end - 0.05;
|
|
82
|
-
}))) return true;
|
|
83
80
|
audioErrors.current++;
|
|
84
81
|
if ((data == null ? void 0 : data.fatal) || audioErrors.current >= 2) return switchSource(true, true);
|
|
85
82
|
if (!audioErrorTimer.current) {
|
|
@@ -96,8 +93,9 @@ function useAudioFallback(options) {
|
|
|
96
93
|
audioErrorTimer.current = null;
|
|
97
94
|
}, []);
|
|
98
95
|
(0, import_react.useEffect)(() => {
|
|
99
|
-
mode.current =
|
|
100
|
-
setVideoOnly(
|
|
96
|
+
mode.current = Boolean(options.fallback);
|
|
97
|
+
setVideoOnly(Boolean(options.fallback));
|
|
98
|
+
progress.current = { time: 0, at: Date.now(), failed: false };
|
|
101
99
|
snapshot.current = null;
|
|
102
100
|
cooldown.current = 0;
|
|
103
101
|
onAudioProgress();
|
|
@@ -105,14 +103,27 @@ function useAudioFallback(options) {
|
|
|
105
103
|
}, [options.primary, options.fallback, onAudioProgress]);
|
|
106
104
|
(0, import_react.useEffect)(() => {
|
|
107
105
|
const check = () => {
|
|
108
|
-
const { ranges, video, fallback } = latest.current;
|
|
109
|
-
if (!fallback
|
|
106
|
+
const { ranges, video, fallback, playingIntent, onStall } = latest.current;
|
|
107
|
+
if (!fallback) return;
|
|
110
108
|
const element = video.current;
|
|
111
109
|
if (!element) return;
|
|
112
110
|
const time = element.currentTime;
|
|
113
|
-
const
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
const previous = progress.current;
|
|
113
|
+
if (!playingIntent.current || element.ended || Math.abs(time - previous.time) > 0.05) {
|
|
114
|
+
progress.current = { time, at: now, failed: false };
|
|
115
|
+
} else if (!previous.failed && now - previous.at >= 8e3) {
|
|
116
|
+
if (!mode.current) switchSource(true, true);
|
|
117
|
+
else {
|
|
118
|
+
progress.current.failed = true;
|
|
119
|
+
onStall == null ? void 0 : onStall();
|
|
120
|
+
}
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (!ranges || snapshot.current) return;
|
|
124
|
+
const available = ranges.some((range) => time >= range.start + 0.1 && time < range.end - 0.1);
|
|
114
125
|
if (!mode.current && !available) switchSource(true);
|
|
115
|
-
else if (mode.current && available &&
|
|
126
|
+
else if (mode.current && available && now >= cooldown.current && ranges.some((range) => time >= range.start + 0.1 && time + 4 <= range.end)) switchSource(false);
|
|
116
127
|
};
|
|
117
128
|
const timer = setInterval(check, 500);
|
|
118
129
|
return () => clearInterval(timer);
|
|
@@ -956,7 +967,9 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
956
967
|
const [, isMobile, mobileType] = useWindowWidth();
|
|
957
968
|
const videoRef = (0, import_react4.useRef)(null);
|
|
958
969
|
const playbackIntent = (0, import_react4.useRef)(autoPlay || defaultPlaying || Boolean(playingProp));
|
|
959
|
-
const
|
|
970
|
+
const stallReporter = (0, import_react4.useRef)(() => {
|
|
971
|
+
});
|
|
972
|
+
const audioFallback = useAudioFallback({ primary: primarySrc, fallback: videoOnlySrc, ranges: audioRanges, video: videoRef, playingIntent: playbackIntent, onChange: onAudioFallbackChange, onStall: () => stallReporter.current() });
|
|
960
973
|
const videoSrc = audioFallback.source;
|
|
961
974
|
const { snapshot: resumeSnapshot, onAudioError, onAudioProgress, switchSource } = audioFallback;
|
|
962
975
|
const hlsRef = (0, import_react4.useRef)(null);
|
|
@@ -1089,6 +1102,16 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1089
1102
|
},
|
|
1090
1103
|
[messages.defaultError, setNextPlaying]
|
|
1091
1104
|
);
|
|
1105
|
+
stallReporter.current = () => {
|
|
1106
|
+
var _a, _b;
|
|
1107
|
+
playbackIntent.current = false;
|
|
1108
|
+
pendingPlay.current = false;
|
|
1109
|
+
reportError("Playback did not advance for 8 seconds", {
|
|
1110
|
+
type: "playback-stalled",
|
|
1111
|
+
src: videoSrc,
|
|
1112
|
+
reason: `readyState=${(_a = videoRef.current) == null ? void 0 : _a.readyState}; buffered=${(_b = videoRef.current) == null ? void 0 : _b.buffered.length}`
|
|
1113
|
+
}, messages.streamLoadFailed);
|
|
1114
|
+
};
|
|
1092
1115
|
const notifyActiveChange = (0, import_react4.useCallback)(
|
|
1093
1116
|
(video, reason) => {
|
|
1094
1117
|
var _a, _b;
|
|
@@ -1404,7 +1427,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1404
1427
|
} else {
|
|
1405
1428
|
h.startLoad();
|
|
1406
1429
|
}
|
|
1407
|
-
if (resumeSnapshot.current ? resumeSnapshot.current.playing : autoPlay) void playAction();
|
|
1430
|
+
if (resumeSnapshot.current ? resumeSnapshot.current.playing : propsRef.current.autoPlay) void playAction();
|
|
1408
1431
|
});
|
|
1409
1432
|
h.on(HlsCtor.Events.FRAG_BUFFERED, (_evt, data) => {
|
|
1410
1433
|
if (isStaleLoad()) return;
|
|
@@ -1441,7 +1464,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1441
1464
|
video.src = videoSrc;
|
|
1442
1465
|
if (!(options == null ? void 0 : options.metadataOnly)) {
|
|
1443
1466
|
video.currentTime = (_b = (_a = resumeSnapshot.current) == null ? void 0 : _a.time) != null ? _b : initialTime;
|
|
1444
|
-
if (resumeSnapshot.current ? resumeSnapshot.current.playing : autoPlay) void playAction();
|
|
1467
|
+
if (resumeSnapshot.current ? resumeSnapshot.current.playing : propsRef.current.autoPlay) void playAction();
|
|
1445
1468
|
}
|
|
1446
1469
|
},
|
|
1447
1470
|
[autoPlay, initialTime, playAction, videoSrc]
|
|
@@ -1657,10 +1680,13 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1657
1680
|
videoSrc
|
|
1658
1681
|
]);
|
|
1659
1682
|
(0, import_react4.useEffect)(() => {
|
|
1660
|
-
if (!autoPlay) return;
|
|
1661
1683
|
if (resumeSnapshot.current) return;
|
|
1662
|
-
if (!canAttemptPlayback(videoRef.current))
|
|
1663
|
-
|
|
1684
|
+
if (!canAttemptPlayback(videoRef.current)) {
|
|
1685
|
+
pendingPlay.current = Boolean(autoPlay);
|
|
1686
|
+
playbackIntent.current = Boolean(autoPlay);
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1689
|
+
if (autoPlay) void playAction();
|
|
1664
1690
|
}, [autoPlay, playAction]);
|
|
1665
1691
|
(0, import_react4.useEffect)(() => {
|
|
1666
1692
|
if (typeof document === "undefined") return;
|
|
@@ -1753,7 +1779,10 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1753
1779
|
setNextPlaying(true);
|
|
1754
1780
|
},
|
|
1755
1781
|
onPause: () => {
|
|
1756
|
-
if (!resumeSnapshot.current)
|
|
1782
|
+
if (!resumeSnapshot.current) {
|
|
1783
|
+
playbackIntent.current = false;
|
|
1784
|
+
setNextPlaying(false);
|
|
1785
|
+
}
|
|
1757
1786
|
},
|
|
1758
1787
|
onEnded: () => setNextPlaying(false),
|
|
1759
1788
|
onLoadedMetadata: videoLoadedHandler,
|
package/dist/index.js
CHANGED
|
@@ -15,8 +15,9 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|
|
15
15
|
function useAudioFallback(options) {
|
|
16
16
|
const latest = useRef(options);
|
|
17
17
|
latest.current = options;
|
|
18
|
-
const [videoOnly, setVideoOnly] = useState(
|
|
19
|
-
const mode = useRef(
|
|
18
|
+
const [videoOnly, setVideoOnly] = useState(Boolean(options.fallback));
|
|
19
|
+
const mode = useRef(Boolean(options.fallback));
|
|
20
|
+
const progress = useRef({ time: 0, at: Date.now(), failed: false });
|
|
20
21
|
const cooldown = useRef(0);
|
|
21
22
|
const audioErrors = useRef(0);
|
|
22
23
|
const audioErrorTimer = useRef(null);
|
|
@@ -33,6 +34,7 @@ function useAudioFallback(options) {
|
|
|
33
34
|
muted: element.muted
|
|
34
35
|
};
|
|
35
36
|
mode.current = next;
|
|
37
|
+
progress.current = { time: element.currentTime, at: Date.now(), failed: false };
|
|
36
38
|
audioErrors.current = 0;
|
|
37
39
|
if (audioErrorTimer.current) clearTimeout(audioErrorTimer.current);
|
|
38
40
|
audioErrorTimer.current = null;
|
|
@@ -42,15 +44,10 @@ function useAudioFallback(options) {
|
|
|
42
44
|
return true;
|
|
43
45
|
}, []);
|
|
44
46
|
const onAudioError = useCallback((data) => {
|
|
45
|
-
var _a, _b
|
|
47
|
+
var _a, _b;
|
|
46
48
|
if (!latest.current.fallback || mode.current) return false;
|
|
47
49
|
const isAudio = ((_a = data == null ? void 0 : data.frag) == null ? void 0 : _a.type) === "audio" || (data == null ? void 0 : data.parent) === "audio" || ((_b = data == null ? void 0 : data.context) == null ? void 0 : _b.type) === "audioTrack" || /^audioTrack/.test((data == null ? void 0 : data.details) || "");
|
|
48
50
|
if (!isAudio) return false;
|
|
49
|
-
if ((data == null ? void 0 : data.details) === "fragGap" && ((_c = latest.current.ranges) == null ? void 0 : _c.some((range) => {
|
|
50
|
-
var _a2, _b2;
|
|
51
|
-
const time = (_b2 = (_a2 = latest.current.video.current) == null ? void 0 : _a2.currentTime) != null ? _b2 : 0;
|
|
52
|
-
return time >= range.start - 0.05 && time < range.end - 0.05;
|
|
53
|
-
}))) return true;
|
|
54
51
|
audioErrors.current++;
|
|
55
52
|
if ((data == null ? void 0 : data.fatal) || audioErrors.current >= 2) return switchSource(true, true);
|
|
56
53
|
if (!audioErrorTimer.current) {
|
|
@@ -67,8 +64,9 @@ function useAudioFallback(options) {
|
|
|
67
64
|
audioErrorTimer.current = null;
|
|
68
65
|
}, []);
|
|
69
66
|
useEffect(() => {
|
|
70
|
-
mode.current =
|
|
71
|
-
setVideoOnly(
|
|
67
|
+
mode.current = Boolean(options.fallback);
|
|
68
|
+
setVideoOnly(Boolean(options.fallback));
|
|
69
|
+
progress.current = { time: 0, at: Date.now(), failed: false };
|
|
72
70
|
snapshot.current = null;
|
|
73
71
|
cooldown.current = 0;
|
|
74
72
|
onAudioProgress();
|
|
@@ -76,14 +74,27 @@ function useAudioFallback(options) {
|
|
|
76
74
|
}, [options.primary, options.fallback, onAudioProgress]);
|
|
77
75
|
useEffect(() => {
|
|
78
76
|
const check = () => {
|
|
79
|
-
const { ranges, video, fallback } = latest.current;
|
|
80
|
-
if (!fallback
|
|
77
|
+
const { ranges, video, fallback, playingIntent, onStall } = latest.current;
|
|
78
|
+
if (!fallback) return;
|
|
81
79
|
const element = video.current;
|
|
82
80
|
if (!element) return;
|
|
83
81
|
const time = element.currentTime;
|
|
84
|
-
const
|
|
82
|
+
const now = Date.now();
|
|
83
|
+
const previous = progress.current;
|
|
84
|
+
if (!playingIntent.current || element.ended || Math.abs(time - previous.time) > 0.05) {
|
|
85
|
+
progress.current = { time, at: now, failed: false };
|
|
86
|
+
} else if (!previous.failed && now - previous.at >= 8e3) {
|
|
87
|
+
if (!mode.current) switchSource(true, true);
|
|
88
|
+
else {
|
|
89
|
+
progress.current.failed = true;
|
|
90
|
+
onStall == null ? void 0 : onStall();
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (!ranges || snapshot.current) return;
|
|
95
|
+
const available = ranges.some((range) => time >= range.start + 0.1 && time < range.end - 0.1);
|
|
85
96
|
if (!mode.current && !available) switchSource(true);
|
|
86
|
-
else if (mode.current && available &&
|
|
97
|
+
else if (mode.current && available && now >= cooldown.current && ranges.some((range) => time >= range.start + 0.1 && time + 4 <= range.end)) switchSource(false);
|
|
87
98
|
};
|
|
88
99
|
const timer = setInterval(check, 500);
|
|
89
100
|
return () => clearInterval(timer);
|
|
@@ -927,7 +938,9 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
927
938
|
const [, isMobile, mobileType] = useWindowWidth();
|
|
928
939
|
const videoRef = useRef3(null);
|
|
929
940
|
const playbackIntent = useRef3(autoPlay || defaultPlaying || Boolean(playingProp));
|
|
930
|
-
const
|
|
941
|
+
const stallReporter = useRef3(() => {
|
|
942
|
+
});
|
|
943
|
+
const audioFallback = useAudioFallback({ primary: primarySrc, fallback: videoOnlySrc, ranges: audioRanges, video: videoRef, playingIntent: playbackIntent, onChange: onAudioFallbackChange, onStall: () => stallReporter.current() });
|
|
931
944
|
const videoSrc = audioFallback.source;
|
|
932
945
|
const { snapshot: resumeSnapshot, onAudioError, onAudioProgress, switchSource } = audioFallback;
|
|
933
946
|
const hlsRef = useRef3(null);
|
|
@@ -1060,6 +1073,16 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1060
1073
|
},
|
|
1061
1074
|
[messages.defaultError, setNextPlaying]
|
|
1062
1075
|
);
|
|
1076
|
+
stallReporter.current = () => {
|
|
1077
|
+
var _a, _b;
|
|
1078
|
+
playbackIntent.current = false;
|
|
1079
|
+
pendingPlay.current = false;
|
|
1080
|
+
reportError("Playback did not advance for 8 seconds", {
|
|
1081
|
+
type: "playback-stalled",
|
|
1082
|
+
src: videoSrc,
|
|
1083
|
+
reason: `readyState=${(_a = videoRef.current) == null ? void 0 : _a.readyState}; buffered=${(_b = videoRef.current) == null ? void 0 : _b.buffered.length}`
|
|
1084
|
+
}, messages.streamLoadFailed);
|
|
1085
|
+
};
|
|
1063
1086
|
const notifyActiveChange = useCallback2(
|
|
1064
1087
|
(video, reason) => {
|
|
1065
1088
|
var _a, _b;
|
|
@@ -1375,7 +1398,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1375
1398
|
} else {
|
|
1376
1399
|
h.startLoad();
|
|
1377
1400
|
}
|
|
1378
|
-
if (resumeSnapshot.current ? resumeSnapshot.current.playing : autoPlay) void playAction();
|
|
1401
|
+
if (resumeSnapshot.current ? resumeSnapshot.current.playing : propsRef.current.autoPlay) void playAction();
|
|
1379
1402
|
});
|
|
1380
1403
|
h.on(HlsCtor.Events.FRAG_BUFFERED, (_evt, data) => {
|
|
1381
1404
|
if (isStaleLoad()) return;
|
|
@@ -1412,7 +1435,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1412
1435
|
video.src = videoSrc;
|
|
1413
1436
|
if (!(options == null ? void 0 : options.metadataOnly)) {
|
|
1414
1437
|
video.currentTime = (_b = (_a = resumeSnapshot.current) == null ? void 0 : _a.time) != null ? _b : initialTime;
|
|
1415
|
-
if (resumeSnapshot.current ? resumeSnapshot.current.playing : autoPlay) void playAction();
|
|
1438
|
+
if (resumeSnapshot.current ? resumeSnapshot.current.playing : propsRef.current.autoPlay) void playAction();
|
|
1416
1439
|
}
|
|
1417
1440
|
},
|
|
1418
1441
|
[autoPlay, initialTime, playAction, videoSrc]
|
|
@@ -1628,10 +1651,13 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1628
1651
|
videoSrc
|
|
1629
1652
|
]);
|
|
1630
1653
|
useEffect2(() => {
|
|
1631
|
-
if (!autoPlay) return;
|
|
1632
1654
|
if (resumeSnapshot.current) return;
|
|
1633
|
-
if (!canAttemptPlayback(videoRef.current))
|
|
1634
|
-
|
|
1655
|
+
if (!canAttemptPlayback(videoRef.current)) {
|
|
1656
|
+
pendingPlay.current = Boolean(autoPlay);
|
|
1657
|
+
playbackIntent.current = Boolean(autoPlay);
|
|
1658
|
+
return;
|
|
1659
|
+
}
|
|
1660
|
+
if (autoPlay) void playAction();
|
|
1635
1661
|
}, [autoPlay, playAction]);
|
|
1636
1662
|
useEffect2(() => {
|
|
1637
1663
|
if (typeof document === "undefined") return;
|
|
@@ -1724,7 +1750,10 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1724
1750
|
setNextPlaying(true);
|
|
1725
1751
|
},
|
|
1726
1752
|
onPause: () => {
|
|
1727
|
-
if (!resumeSnapshot.current)
|
|
1753
|
+
if (!resumeSnapshot.current) {
|
|
1754
|
+
playbackIntent.current = false;
|
|
1755
|
+
setNextPlaying(false);
|
|
1756
|
+
}
|
|
1728
1757
|
},
|
|
1729
1758
|
onEnded: () => setNextPlaying(false),
|
|
1730
1759
|
onLoadedMetadata: videoLoadedHandler,
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nikelroot/video-player",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Standalone React video player with HLS support.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://gitlab.nikelroot.ru/home/nvideoplayer.git"
|
|
8
|
+
},
|
|
5
9
|
"type": "module",
|
|
6
10
|
"main": "./dist/index.cjs",
|
|
7
11
|
"module": "./dist/index.js",
|
|
@@ -41,6 +45,8 @@
|
|
|
41
45
|
"typescript": "^5.9.3"
|
|
42
46
|
},
|
|
43
47
|
"publishConfig": {
|
|
44
|
-
"access": "public"
|
|
45
|
-
|
|
48
|
+
"access": "public",
|
|
49
|
+
"registry": "https://registry.npmjs.org/"
|
|
50
|
+
},
|
|
51
|
+
"gitHead": "00fca415c7ef041917872f1349ff3739b1b8da47"
|
|
46
52
|
}
|