customvidplayer 0.0.14 → 0.0.16
Sign up to get free protection for your applications and to get access to all the features.
@@ -11,6 +11,7 @@ declare namespace VideoPlayer {
|
|
11
11
|
const sections: PropTypes.Validator<(PropTypes.InferProps<{
|
12
12
|
name: PropTypes.Validator<string>;
|
13
13
|
timestamp: PropTypes.Validator<number>;
|
14
|
+
color: PropTypes.Requireable<string>;
|
14
15
|
}> | null | undefined)[]>;
|
15
16
|
const onSectionChange: PropTypes.Requireable<(...args: any[]) => any>;
|
16
17
|
const theme: PropTypes.Requireable<object>;
|
@@ -61,6 +61,9 @@ var VideoPlayer = function VideoPlayer(_a) {
|
|
61
61
|
var _b = (0, react_1.useState)(0),
|
62
62
|
currentSectionIndex = _b[0],
|
63
63
|
setCurrentSectionIndex = _b[1];
|
64
|
+
var _c = (0, react_1.useState)(false),
|
65
|
+
isPlaying = _c[0],
|
66
|
+
setIsPlaying = _c[1];
|
64
67
|
var skipToNextSection = function skipToNextSection() {
|
65
68
|
if (currentSectionIndex < sections.length - 1) {
|
66
69
|
var nextSection = sections[currentSectionIndex + 1];
|
@@ -70,14 +73,29 @@ var VideoPlayer = function VideoPlayer(_a) {
|
|
70
73
|
}
|
71
74
|
};
|
72
75
|
var handleTimeUpdate = function handleTimeUpdate() {
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
if (videoRef.current) {
|
77
|
+
var currentTime_1 = videoRef.current.currentTime;
|
78
|
+
var currentSection = sections.find(function (section, index) {
|
79
|
+
return currentTime_1 >= section.timestamp && (index === sections.length - 1 || currentTime_1 < sections[index + 1].timestamp);
|
80
|
+
});
|
81
|
+
if (currentSection && sections[currentSectionIndex] !== currentSection) {
|
82
|
+
var newIndex = sections.indexOf(currentSection);
|
83
|
+
setCurrentSectionIndex(newIndex);
|
84
|
+
if (onSectionChange) onSectionChange(currentSection);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
};
|
88
|
+
var playVideo = function playVideo() {
|
89
|
+
videoRef.current.play();
|
90
|
+
setIsPlaying(true);
|
91
|
+
};
|
92
|
+
var pauseVideo = function pauseVideo() {
|
93
|
+
videoRef.current.pause();
|
94
|
+
setIsPlaying(false);
|
95
|
+
};
|
96
|
+
var skipForward = function skipForward() {
|
97
|
+
if (videoRef.current) {
|
98
|
+
videoRef.current.currentTime += 10;
|
81
99
|
}
|
82
100
|
};
|
83
101
|
return react_1["default"].createElement("div", {
|
@@ -85,20 +103,41 @@ var VideoPlayer = function VideoPlayer(_a) {
|
|
85
103
|
style: __assign({}, theme)
|
86
104
|
}, react_1["default"].createElement("video", {
|
87
105
|
src: videoSrc,
|
88
|
-
controls:
|
106
|
+
controls: false,
|
89
107
|
ref: videoRef,
|
90
108
|
onTimeUpdate: handleTimeUpdate,
|
91
109
|
className: "video-element"
|
92
|
-
}), react_1["default"].createElement("
|
110
|
+
}), react_1["default"].createElement("div", {
|
111
|
+
className: "bottom-bar",
|
112
|
+
style: {
|
113
|
+
backgroundColor: theme.bottomBarColor || '#000'
|
114
|
+
}
|
115
|
+
}, react_1["default"].createElement("button", {
|
116
|
+
onClick: isPlaying ? pauseVideo : playVideo
|
117
|
+
}, isPlaying ? 'Pause' : 'Play'), react_1["default"].createElement("button", {
|
118
|
+
onClick: skipForward
|
119
|
+
}, "Skip 10s"), react_1["default"].createElement("button", {
|
93
120
|
onClick: skipToNextSection,
|
94
121
|
className: "skip-button"
|
95
|
-
}, "Skip"))
|
122
|
+
}, "Skip")), react_1["default"].createElement("div", {
|
123
|
+
className: "progress-bar"
|
124
|
+
}, sections.map(function (section, index) {
|
125
|
+
return react_1["default"].createElement("div", {
|
126
|
+
key: index,
|
127
|
+
className: "section-indicator",
|
128
|
+
style: {
|
129
|
+
left: videoRef.current ? "".concat(section.timestamp / videoRef.current.duration * 100, "%") : '0%',
|
130
|
+
backgroundColor: section.color || '#007bff'
|
131
|
+
}
|
132
|
+
}, section.name);
|
133
|
+
})));
|
96
134
|
};
|
97
135
|
VideoPlayer.propTypes = {
|
98
136
|
videoSrc: prop_types_1["default"].string.isRequired,
|
99
137
|
sections: prop_types_1["default"].arrayOf(prop_types_1["default"].shape({
|
100
138
|
name: prop_types_1["default"].string.isRequired,
|
101
|
-
timestamp: prop_types_1["default"].number.isRequired
|
139
|
+
timestamp: prop_types_1["default"].number.isRequired,
|
140
|
+
color: prop_types_1["default"].string
|
102
141
|
})).isRequired,
|
103
142
|
onSectionChange: prop_types_1["default"].func,
|
104
143
|
theme: prop_types_1["default"].object
|
package/package.json
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
import React, { useState, useRef } from "react";
|
1
|
+
import React, { useState, useRef, useEffect } from "react";
|
2
2
|
import PropTypes from "prop-types";
|
3
3
|
import "./../styles/defaultTheme.css";
|
4
4
|
|
5
5
|
const VideoPlayer = ({ videoSrc, sections, onSectionChange, theme }) => {
|
6
6
|
const videoRef = useRef(null);
|
7
7
|
const [currentSectionIndex, setCurrentSectionIndex] = useState(0);
|
8
|
+
const [isPlaying, setIsPlaying] = useState(false);
|
8
9
|
|
9
10
|
const skipToNextSection = () => {
|
10
11
|
if (currentSectionIndex < sections.length - 1) {
|
@@ -16,17 +17,35 @@ const VideoPlayer = ({ videoSrc, sections, onSectionChange, theme }) => {
|
|
16
17
|
};
|
17
18
|
|
18
19
|
const handleTimeUpdate = () => {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
if (videoRef.current) {
|
21
|
+
const currentTime = videoRef.current.currentTime;
|
22
|
+
const currentSection = sections.find(
|
23
|
+
(section, index) =>
|
24
|
+
currentTime >= section.timestamp &&
|
25
|
+
(index === sections.length - 1 || currentTime < sections[index + 1].timestamp)
|
26
|
+
);
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
if (currentSection && sections[currentSectionIndex] !== currentSection) {
|
29
|
+
const newIndex = sections.indexOf(currentSection);
|
30
|
+
setCurrentSectionIndex(newIndex);
|
31
|
+
if (onSectionChange) onSectionChange(currentSection);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
};
|
35
|
+
|
36
|
+
const playVideo = () => {
|
37
|
+
videoRef.current.play();
|
38
|
+
setIsPlaying(true);
|
39
|
+
};
|
40
|
+
|
41
|
+
const pauseVideo = () => {
|
42
|
+
videoRef.current.pause();
|
43
|
+
setIsPlaying(false);
|
44
|
+
};
|
45
|
+
|
46
|
+
const skipForward = () => {
|
47
|
+
if (videoRef.current) {
|
48
|
+
videoRef.current.currentTime += 10;
|
30
49
|
}
|
31
50
|
};
|
32
51
|
|
@@ -34,14 +53,34 @@ const VideoPlayer = ({ videoSrc, sections, onSectionChange, theme }) => {
|
|
34
53
|
<div className="video-player" style={{ ...theme }}>
|
35
54
|
<video
|
36
55
|
src={videoSrc}
|
37
|
-
controls
|
56
|
+
controls={false}
|
38
57
|
ref={videoRef}
|
39
58
|
onTimeUpdate={handleTimeUpdate}
|
40
59
|
className="video-element"
|
41
60
|
/>
|
42
|
-
<
|
43
|
-
|
44
|
-
|
61
|
+
<div className="bottom-bar" style={{ backgroundColor: theme.bottomBarColor || '#000' }}>
|
62
|
+
<button onClick={isPlaying ? pauseVideo : playVideo}>
|
63
|
+
{isPlaying ? 'Pause' : 'Play'}
|
64
|
+
</button>
|
65
|
+
<button onClick={skipForward}>Skip 10s</button>
|
66
|
+
<button onClick={skipToNextSection} className="skip-button">
|
67
|
+
Skip
|
68
|
+
</button>
|
69
|
+
</div>
|
70
|
+
<div className="progress-bar">
|
71
|
+
{sections.map((section, index) => (
|
72
|
+
<div
|
73
|
+
key={index}
|
74
|
+
className="section-indicator"
|
75
|
+
style={{
|
76
|
+
left: videoRef.current ? `${(section.timestamp / videoRef.current.duration) * 100}%` : '0%',
|
77
|
+
backgroundColor: section.color || '#007bff',
|
78
|
+
}}
|
79
|
+
>
|
80
|
+
{section.name}
|
81
|
+
</div>
|
82
|
+
))}
|
83
|
+
</div>
|
45
84
|
</div>
|
46
85
|
);
|
47
86
|
};
|
@@ -52,6 +91,7 @@ VideoPlayer.propTypes = {
|
|
52
91
|
PropTypes.shape({
|
53
92
|
name: PropTypes.string.isRequired,
|
54
93
|
timestamp: PropTypes.number.isRequired,
|
94
|
+
color: PropTypes.string,
|
55
95
|
})
|
56
96
|
).isRequired,
|
57
97
|
onSectionChange: PropTypes.func,
|
@@ -27,4 +27,24 @@
|
|
27
27
|
margin: 5px 0;
|
28
28
|
color: #007bff;
|
29
29
|
}
|
30
|
+
|
31
|
+
.bottom-bar {
|
32
|
+
display: flex;
|
33
|
+
justify-content: space-between;
|
34
|
+
padding: 10px;
|
35
|
+
}
|
36
|
+
|
37
|
+
.progress-bar {
|
38
|
+
position: relative;
|
39
|
+
height: 5px;
|
40
|
+
background: #ccc;
|
41
|
+
margin-top: 5px;
|
42
|
+
}
|
43
|
+
|
44
|
+
.section-indicator {
|
45
|
+
position: absolute;
|
46
|
+
width: 5px;
|
47
|
+
height: 100%;
|
48
|
+
background: #007bff; /* Default color */
|
49
|
+
}
|
30
50
|
|