l-min-components 1.0.525 → 1.0.528
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/package.json +2 -1
- package/src/components/index.js +1 -0
- package/src/components/{videoPlayer → video-player}/icons/pause.jsx +0 -1
- package/src/components/{videoPlayer → video-player}/icons/playVideoIcon.jsx +0 -1
- package/src/components/{videoPlayer → video-player}/icons/videoScreenIcon.jsx +0 -1
- package/src/components/video-player/index.jsx +238 -0
- package/src/components/{videoPlayer → video-player}/index.styled.jsx +14 -1
- package/src/components/videoPlayer/index.jsx +0 -163
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "l-min-components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.528",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"src/assets",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"react-lottie": "^1.2.4",
|
|
43
43
|
"react-mic": "^12.4.6",
|
|
44
44
|
"react-modal": "^3.16.1",
|
|
45
|
+
"react-player": "^2.14.1",
|
|
45
46
|
"react-router-dom": "^6.8.2",
|
|
46
47
|
"react-toastify": "^9.1.3",
|
|
47
48
|
"react-tooltip": "^5.10.1",
|
package/src/components/index.js
CHANGED
|
@@ -38,3 +38,4 @@ export { default as EnterpriseRightBar } from "./fileRightBar/enterpriseRightBar
|
|
|
38
38
|
export { default as FullPageLoader } from "./fullPageLoader";
|
|
39
39
|
export { default as AdminAppMainLayout } from "./AdminAppMainLayout";
|
|
40
40
|
export { default as PaginationComponent } from "./paginate";
|
|
41
|
+
export { default as VideoPlayer } from "./video-player";
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import React, { useState, useRef, useEffect, useContext } from "react";
|
|
2
|
+
import { OutletContext } from "../AppMainLayout";
|
|
3
|
+
import screenfull from "screenfull";
|
|
4
|
+
import {
|
|
5
|
+
LoadingScreen,
|
|
6
|
+
RangeContainer,
|
|
7
|
+
VideoController,
|
|
8
|
+
VideoPlayerContainer,
|
|
9
|
+
VideoPrompts,
|
|
10
|
+
} from "./index.styled";
|
|
11
|
+
import ReactPlayer from "react-player";
|
|
12
|
+
import VideoScreenIcon from "./icons/videoScreenIcon";
|
|
13
|
+
import PlayIcon from "./icons/playVideoIcon";
|
|
14
|
+
import PauseIcon from "./icons/pause";
|
|
15
|
+
// import LoaderCustom from "../loader";
|
|
16
|
+
import FullPageLoader from "../fullPageLoader";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @param {object} props
|
|
21
|
+
* @param {string} props.width - Width of the player in px
|
|
22
|
+
* @param {string} props.height - Height of the player in px
|
|
23
|
+
* @param {React.CSSProperties} props.style - Player container style
|
|
24
|
+
* @param {boolean} props.hideRange - To hide the range controller
|
|
25
|
+
* @param {boolean} props.showPrompts - show next and prev controller
|
|
26
|
+
* @param {string} props.src - Video source url
|
|
27
|
+
* @param {string} props.streamUrl - Stream video url
|
|
28
|
+
* @param {string} props.thumbnailSrc - Thumbnail url
|
|
29
|
+
* @returns {JSX.Element}
|
|
30
|
+
*/
|
|
31
|
+
const VideoPlayer = ({
|
|
32
|
+
width,
|
|
33
|
+
height = "360px",
|
|
34
|
+
style,
|
|
35
|
+
hideRange,
|
|
36
|
+
showPrompts,
|
|
37
|
+
src,
|
|
38
|
+
streamUrl,
|
|
39
|
+
thumbnailSrc,
|
|
40
|
+
}) => {
|
|
41
|
+
const [isPlaying, setIsPlayering] = useState(false);
|
|
42
|
+
const [isSeeking, setIsSeeking] = useState(false);
|
|
43
|
+
const [progress, setProgress] = useState();
|
|
44
|
+
const [hideController, setHideController] = useState(false);
|
|
45
|
+
const [count, setCount] = useState(0);
|
|
46
|
+
const playContainerRef = useRef();
|
|
47
|
+
const [url, setUrl] = useState(null);
|
|
48
|
+
const [image, setImage] = useState(null);
|
|
49
|
+
const playerRef = useRef();
|
|
50
|
+
const { accessToken } = useContext(OutletContext);
|
|
51
|
+
const [isReady, setIsReady] = useState(false);
|
|
52
|
+
const [rangeProgress, setRangeProgress] = useState(0);
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (src || streamUrl) {
|
|
56
|
+
setUrl(src ? src : `https://dev-117782726-api.learngual.com${streamUrl}`);
|
|
57
|
+
}
|
|
58
|
+
if (thumbnailSrc) {
|
|
59
|
+
setImage(thumbnailSrc);
|
|
60
|
+
}
|
|
61
|
+
}, [streamUrl, thumbnailSrc, src]);
|
|
62
|
+
|
|
63
|
+
const format = (secs) => {
|
|
64
|
+
const sec_num = parseInt(secs, 10);
|
|
65
|
+
const hours = Math.floor(sec_num / 3600);
|
|
66
|
+
const minutes = Math.floor(sec_num / 60) % 60;
|
|
67
|
+
const seconds = sec_num % 60;
|
|
68
|
+
|
|
69
|
+
return [hours, minutes, seconds]
|
|
70
|
+
.map((v) => (v < 10 ? "0" + v : v))
|
|
71
|
+
.join(":");
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const handlePlayPause = () => {
|
|
75
|
+
setIsPlayering(!isPlaying);
|
|
76
|
+
setImage(null);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const handleFullScreen = () => {
|
|
80
|
+
screenfull.toggle(playContainerRef.current);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const handleProgress = (progress) => {
|
|
84
|
+
if (count > 3) {
|
|
85
|
+
setHideController(true);
|
|
86
|
+
setCount(0);
|
|
87
|
+
}
|
|
88
|
+
if (!hideController) {
|
|
89
|
+
setCount(count + 1);
|
|
90
|
+
}
|
|
91
|
+
if (!isSeeking) {
|
|
92
|
+
setRangeProgress(progress?.played);
|
|
93
|
+
setProgress(progress);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const handleSeekChange = (e) => {
|
|
98
|
+
const value = parseFloat(e.target.value) / 100;
|
|
99
|
+
setRangeProgress(value);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const handleSeekMouseUp = () => {
|
|
103
|
+
setIsSeeking(false);
|
|
104
|
+
playerRef.current?.seekTo(rangeProgress, "fraction");
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const handleSeekMouseDown = () => {
|
|
108
|
+
setIsSeeking(true);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const handleMouseMove = () => {
|
|
112
|
+
setHideController(false);
|
|
113
|
+
setCount(0);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const calcShowPrompts = () => {
|
|
117
|
+
if (progress?.playedSeconds) {
|
|
118
|
+
return Math.floor(
|
|
119
|
+
(progress.playedSeconds * 100) / progress.loadedSeconds,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const currentTime = playerRef.current?.getCurrentTime()
|
|
125
|
+
? format(playerRef.current?.getCurrentTime())
|
|
126
|
+
: "00:00:00";
|
|
127
|
+
|
|
128
|
+
const duration = playerRef.current?.getDuration()
|
|
129
|
+
? format(playerRef.current?.getDuration())
|
|
130
|
+
: "00:00:00";
|
|
131
|
+
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (progress?.loaded) {
|
|
134
|
+
setIsReady(true);
|
|
135
|
+
} else {
|
|
136
|
+
setIsReady(false);
|
|
137
|
+
}
|
|
138
|
+
}, [progress?.loaded]);
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<VideoPlayerContainer
|
|
142
|
+
ref={playContainerRef}
|
|
143
|
+
style={style}
|
|
144
|
+
width={width}
|
|
145
|
+
height={height}
|
|
146
|
+
onMouseMove={handleMouseMove}
|
|
147
|
+
>
|
|
148
|
+
{showPrompts && calcShowPrompts() > 80 && (
|
|
149
|
+
<VideoPrompts>
|
|
150
|
+
<div>
|
|
151
|
+
<p>Continue watching</p>
|
|
152
|
+
<p>Previuos Part (Lesson 1)</p>
|
|
153
|
+
</div>
|
|
154
|
+
<div>
|
|
155
|
+
<p>Continue watching</p>
|
|
156
|
+
<p>Next Part (Lesson 6)</p>
|
|
157
|
+
</div>
|
|
158
|
+
</VideoPrompts>
|
|
159
|
+
)}
|
|
160
|
+
{!isReady && !image && (
|
|
161
|
+
<LoadingScreen>
|
|
162
|
+
{/* <LoaderCustom zoom={0.5} /> */}
|
|
163
|
+
<FullPageLoader isSectionLoader loaderWidth={300} />
|
|
164
|
+
</LoadingScreen>
|
|
165
|
+
)}
|
|
166
|
+
<ReactPlayer
|
|
167
|
+
width="100%"
|
|
168
|
+
ref={playerRef}
|
|
169
|
+
height="100%"
|
|
170
|
+
url={url}
|
|
171
|
+
// muted={true}
|
|
172
|
+
step="any"
|
|
173
|
+
light={image}
|
|
174
|
+
playing={isPlaying}
|
|
175
|
+
onProgress={handleProgress}
|
|
176
|
+
onEnded={() => {
|
|
177
|
+
setIsPlayering(false);
|
|
178
|
+
setHideController(false);
|
|
179
|
+
setCount(0);
|
|
180
|
+
setProgress({ ...progress, played: 1 });
|
|
181
|
+
}}
|
|
182
|
+
config={
|
|
183
|
+
streamUrl
|
|
184
|
+
? {
|
|
185
|
+
file: {
|
|
186
|
+
forceHLS: true,
|
|
187
|
+
hlsOptions: {
|
|
188
|
+
xhrSetup: function (xhr, url) {
|
|
189
|
+
if (accessToken) {
|
|
190
|
+
const modifiedURL = `${url}?_account=7d5529dcf5`;
|
|
191
|
+
xhr.open("GET", modifiedURL, true);
|
|
192
|
+
xhr.setRequestHeader(
|
|
193
|
+
"Authorization",
|
|
194
|
+
`Bearer ${accessToken}`,
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
hls: {
|
|
201
|
+
enableLowInitialLatency: true,
|
|
202
|
+
smoothQualityChange: true,
|
|
203
|
+
startLevel: 0,
|
|
204
|
+
},
|
|
205
|
+
}
|
|
206
|
+
: { file: null, hls: null }
|
|
207
|
+
}
|
|
208
|
+
/>
|
|
209
|
+
<VideoController hide={hideController}>
|
|
210
|
+
{!hideRange && (!image || !isReady) && (
|
|
211
|
+
<RangeContainer>
|
|
212
|
+
<p>
|
|
213
|
+
{currentTime} / {duration}
|
|
214
|
+
</p>
|
|
215
|
+
<input
|
|
216
|
+
type="range"
|
|
217
|
+
min={0}
|
|
218
|
+
max={100}
|
|
219
|
+
className="range"
|
|
220
|
+
onChange={handleSeekChange}
|
|
221
|
+
onMouseDown={handleSeekMouseDown}
|
|
222
|
+
onMouseUp={handleSeekMouseUp}
|
|
223
|
+
value={rangeProgress * 100}
|
|
224
|
+
/>
|
|
225
|
+
<VideoScreenIcon onClick={handleFullScreen} />
|
|
226
|
+
</RangeContainer>
|
|
227
|
+
)}
|
|
228
|
+
{(isReady || image) && (
|
|
229
|
+
<div className="play_pause_wrap" onClick={handlePlayPause}>
|
|
230
|
+
{isPlaying ? <PauseIcon fill="#fff" /> : <PlayIcon fill="#fff" />}
|
|
231
|
+
</div>
|
|
232
|
+
)}
|
|
233
|
+
</VideoController>
|
|
234
|
+
</VideoPlayerContainer>
|
|
235
|
+
);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export default VideoPlayer;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import styled from "styled-components";
|
|
1
|
+
import { styled } from "styled-components";
|
|
2
2
|
|
|
3
3
|
export const VideoPlayerContainer = styled.div`
|
|
4
4
|
position: relative;
|
|
5
5
|
border-radius: 24px;
|
|
6
6
|
overflow: hidden;
|
|
7
|
+
/* background: #f5f7f7; */
|
|
7
8
|
width: ${({ width }) => (width ? width : "auto")};
|
|
8
9
|
height: ${({ height }) => (height ? height : "auto")};
|
|
9
10
|
video {
|
|
@@ -146,3 +147,15 @@ export const VideoPrompts = styled.div`
|
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
`;
|
|
150
|
+
|
|
151
|
+
export const LoadingScreen = styled.div`
|
|
152
|
+
position: absolute;
|
|
153
|
+
top: 0;
|
|
154
|
+
left: 0;
|
|
155
|
+
right: 0;
|
|
156
|
+
bottom: 0;
|
|
157
|
+
z-index: 40;
|
|
158
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
159
|
+
display: grid;
|
|
160
|
+
place-items: center;
|
|
161
|
+
`;
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { useState, useRef } from "react";
|
|
3
|
-
import screenfull from "screenfull";
|
|
4
|
-
import {
|
|
5
|
-
RangeContainer,
|
|
6
|
-
VideoController,
|
|
7
|
-
VideoPlayerContainer,
|
|
8
|
-
VideoPrompts,
|
|
9
|
-
} from "./index.styled";
|
|
10
|
-
import ReactPlayer from "react-player";
|
|
11
|
-
import VideoScreenIcon from "./icons/videoScreenIcon";
|
|
12
|
-
import PlayIcon from "./icons/playVideoIcon";
|
|
13
|
-
import PauseIcon from "./icons/pause";
|
|
14
|
-
|
|
15
|
-
const VideoPlayer = ({
|
|
16
|
-
width,
|
|
17
|
-
height = "360px",
|
|
18
|
-
style,
|
|
19
|
-
src,
|
|
20
|
-
hideRange,
|
|
21
|
-
showPrompts,
|
|
22
|
-
controlSize,
|
|
23
|
-
}) => {
|
|
24
|
-
const [isPlaying, setIsPlayering] = useState(false);
|
|
25
|
-
const [isSeeking, setIsSeeking] = useState(false);
|
|
26
|
-
const [progress, setProgress] = useState();
|
|
27
|
-
const [hideController, setHideController] = useState(false);
|
|
28
|
-
const [count, setCount] = useState(0);
|
|
29
|
-
const playContainerRef = useRef();
|
|
30
|
-
const playerRef = useRef();
|
|
31
|
-
|
|
32
|
-
const format = (secs) => {
|
|
33
|
-
const sec_num = parseInt(secs, 10);
|
|
34
|
-
const hours = Math.floor(sec_num / 3600);
|
|
35
|
-
const minutes = Math.floor(sec_num / 60) % 60;
|
|
36
|
-
const seconds = sec_num % 60;
|
|
37
|
-
|
|
38
|
-
return [hours, minutes, seconds]
|
|
39
|
-
.map((v) => (v < 10 ? "0" + v : v))
|
|
40
|
-
.join(":");
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const handlePlayPause = () => {
|
|
44
|
-
setIsPlayering(!isPlaying);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const handleFullScreen = () => {
|
|
48
|
-
screenfull.toggle(playContainerRef.current);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const handleProgess = (changeState) => {
|
|
52
|
-
if (count > 3) {
|
|
53
|
-
setHideController(true);
|
|
54
|
-
setCount(0);
|
|
55
|
-
}
|
|
56
|
-
if (!hideController) {
|
|
57
|
-
setCount(count + 1);
|
|
58
|
-
}
|
|
59
|
-
if (isSeeking === false) {
|
|
60
|
-
setProgress(changeState);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const handleSeek = (e) => {
|
|
65
|
-
setProgress({ ...progress, played: parseFloat(e.target?.value / 100) });
|
|
66
|
-
};
|
|
67
|
-
const handleSeekMouseDown = () => {
|
|
68
|
-
setIsSeeking(true);
|
|
69
|
-
};
|
|
70
|
-
const handleSeekMouseUp = (e) => {
|
|
71
|
-
setIsSeeking(true);
|
|
72
|
-
playerRef.current?.seekTo(e.target?.value / 100);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const handleMouseMove = () => {
|
|
76
|
-
setHideController(false);
|
|
77
|
-
setCount(0);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const calcShowPrompts = () => {
|
|
81
|
-
if (progress?.playedSeconds) {
|
|
82
|
-
return Math.floor(
|
|
83
|
-
(progress.playedSeconds * 100) / progress.loadedSeconds
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const currentTime = playerRef.current
|
|
89
|
-
? format(playerRef.current?.getCurrentTime())
|
|
90
|
-
: "00:00:00";
|
|
91
|
-
|
|
92
|
-
const duration = playerRef.current
|
|
93
|
-
? format(playerRef.current?.getDuration())
|
|
94
|
-
: "00:00:00";
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<VideoPlayerContainer
|
|
98
|
-
ref={playContainerRef}
|
|
99
|
-
style={style}
|
|
100
|
-
width={width}
|
|
101
|
-
height={height}
|
|
102
|
-
onMouseMove={handleMouseMove}
|
|
103
|
-
>
|
|
104
|
-
{showPrompts && calcShowPrompts() > 80 && (
|
|
105
|
-
<VideoPrompts>
|
|
106
|
-
<div>
|
|
107
|
-
<p>Continue watching</p>
|
|
108
|
-
<p>Previuos Part (Lesson 1)</p>
|
|
109
|
-
</div>
|
|
110
|
-
<div>
|
|
111
|
-
<p>Continue watching</p>
|
|
112
|
-
<p>Next Part (Lesson 6)</p>
|
|
113
|
-
</div>
|
|
114
|
-
</VideoPrompts>
|
|
115
|
-
)}
|
|
116
|
-
<ReactPlayer
|
|
117
|
-
width="100%"
|
|
118
|
-
ref={playerRef}
|
|
119
|
-
height="100%"
|
|
120
|
-
url={
|
|
121
|
-
src ||
|
|
122
|
-
"https://joy1.videvo.net/videvo_files/video/free/video0474/small_watermarked/_import_61ea3dd6ab62a0.19123787_preview.mp4"
|
|
123
|
-
}
|
|
124
|
-
// muted={true}
|
|
125
|
-
playing={isPlaying}
|
|
126
|
-
onProgress={handleProgess}
|
|
127
|
-
onEnded={() => {
|
|
128
|
-
setIsPlayering(false);
|
|
129
|
-
setHideController(false);
|
|
130
|
-
setCount(0);
|
|
131
|
-
setProgress({ ...progress, played: 1 });
|
|
132
|
-
}}
|
|
133
|
-
/>
|
|
134
|
-
<VideoController hide={hideController} size={controlSize}>
|
|
135
|
-
{!hideRange && (
|
|
136
|
-
<RangeContainer>
|
|
137
|
-
<p>
|
|
138
|
-
{currentTime} / {duration}
|
|
139
|
-
</p>
|
|
140
|
-
<input
|
|
141
|
-
type="range"
|
|
142
|
-
name=""
|
|
143
|
-
id=""
|
|
144
|
-
className="range"
|
|
145
|
-
min={0}
|
|
146
|
-
max={100}
|
|
147
|
-
onChange={handleSeek}
|
|
148
|
-
onMouseDown={handleSeekMouseDown}
|
|
149
|
-
onMouseUp={handleSeekMouseUp}
|
|
150
|
-
value={Math.round(progress?.played * 100)}
|
|
151
|
-
/>
|
|
152
|
-
<VideoScreenIcon onClick={handleFullScreen} />
|
|
153
|
-
</RangeContainer>
|
|
154
|
-
)}
|
|
155
|
-
<div className="play_pause_wrap" onClick={handlePlayPause}>
|
|
156
|
-
{isPlaying ? <PauseIcon fill="#fff" /> : <PlayIcon fill="#fff" />}
|
|
157
|
-
</div>
|
|
158
|
-
</VideoController>
|
|
159
|
-
</VideoPlayerContainer>
|
|
160
|
-
);
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
export default VideoPlayer;
|