ChandimaPrabath
commited on
Commit
•
6b07118
1
Parent(s):
3236c88
google-site-verification
Browse files
frontend/src/app/layout.js
CHANGED
@@ -17,7 +17,8 @@ export default function RootLayout({ children }) {
|
|
17 |
<body className={inter.className}>
|
18 |
<Providers>
|
19 |
<header>
|
20 |
-
<link rel="manifest" href="webmanifest.json" />
|
|
|
21 |
<Header />
|
22 |
</header>
|
23 |
<TvShowsProvider>
|
|
|
17 |
<body className={inter.className}>
|
18 |
<Providers>
|
19 |
<header>
|
20 |
+
<link rel="manifest" href="/webmanifest.json" />
|
21 |
+
<meta name="google-site-verification" content="I0Ek30weBtiN05x5O5wID0tPEPuo7ZCippWfbOWc4yo"/>
|
22 |
<Header />
|
23 |
</header>
|
24 |
<TvShowsProvider>
|
frontend/src/components/Player/Movie/MoviePlayer.js
CHANGED
@@ -28,9 +28,13 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
28 |
const [buffer, setBuffer] = useState(0); // Buffer state
|
29 |
const [isFullscreen, setIsFullscreen] = useState(false);
|
30 |
const [showControls, setShowControls] = useState(true);
|
31 |
-
const [isBuffering, setIsBuffering] = useState(
|
32 |
const overlayTimeout = useRef(null);
|
33 |
-
const [contextMenu, setContextMenu] = useState({
|
|
|
|
|
|
|
|
|
34 |
const playerVersion = "0.0.2 Alpha";
|
35 |
|
36 |
useEffect(() => {
|
@@ -45,6 +49,8 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
45 |
const handleWaiting = () => setIsBuffering(true);
|
46 |
const handlePlaying = () => setIsBuffering(false);
|
47 |
const handleProgress = () => updateBuffer(); // Update buffer on progress
|
|
|
|
|
48 |
|
49 |
videoElement.addEventListener("play", handlePlay);
|
50 |
videoElement.addEventListener("pause", handlePause);
|
@@ -52,6 +58,8 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
52 |
videoElement.addEventListener("waiting", handleWaiting);
|
53 |
videoElement.addEventListener("playing", handlePlaying);
|
54 |
videoElement.addEventListener("progress", handleProgress); // Listen to progress events
|
|
|
|
|
55 |
|
56 |
return () => {
|
57 |
videoElement.removeEventListener("play", handlePlay);
|
@@ -60,6 +68,8 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
60 |
videoElement.removeEventListener("waiting", handleWaiting);
|
61 |
videoElement.removeEventListener("playing", handlePlaying);
|
62 |
videoElement.removeEventListener("progress", handleProgress); // Clean up progress listener
|
|
|
|
|
63 |
};
|
64 |
}, []);
|
65 |
|
@@ -164,7 +174,8 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
164 |
};
|
165 |
|
166 |
const handleSeek = (newProgress) => {
|
167 |
-
videoRef.current.currentTime =
|
|
|
168 |
setProgress(newProgress);
|
169 |
};
|
170 |
|
@@ -174,23 +185,25 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
174 |
|
175 |
const formatTime = (seconds) => {
|
176 |
if (isNaN(seconds)) {
|
177 |
-
return
|
178 |
}
|
179 |
const wholeSeconds = Math.floor(seconds);
|
180 |
const hours = Math.floor(wholeSeconds / 3600);
|
181 |
const minutes = Math.floor((wholeSeconds % 3600) / 60);
|
182 |
const secs = wholeSeconds % 60;
|
183 |
|
184 |
-
const formattedHours = String(hours).padStart(2,
|
185 |
-
const formattedMinutes = String(minutes).padStart(2,
|
186 |
-
const formattedSeconds = String(secs).padStart(2,
|
187 |
return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
|
188 |
};
|
189 |
|
190 |
const updateBuffer = () => {
|
191 |
const videoElement = videoRef.current;
|
192 |
if (videoElement.buffered.length > 0) {
|
193 |
-
const bufferEnd = videoElement.buffered.end(
|
|
|
|
|
194 |
const bufferValue = (bufferEnd / videoElement.duration) * 100;
|
195 |
setBuffer(bufferValue);
|
196 |
}
|
@@ -201,26 +214,35 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
201 |
};
|
202 |
|
203 |
return (
|
204 |
-
<div
|
|
|
|
|
|
|
|
|
205 |
<div className={`player-overlay ${showControls ? "show" : "hide"}`}>
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
<div className="controls">
|
213 |
<div className="player-controls-top">
|
214 |
-
<label className="current-time">
|
215 |
-
|
216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
</div>
|
218 |
<div className="player-controls-down">
|
219 |
<div className="player-controls-left">
|
220 |
-
<button
|
221 |
-
onClick={handleRewind}
|
222 |
-
className="control-btn"
|
223 |
-
>
|
224 |
<FontAwesomeIcon icon={faAngleDoubleLeft} size="xl" />
|
225 |
</button>
|
226 |
<button onClick={togglePlayPause} className="play-pause-btn">
|
@@ -230,10 +252,7 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
230 |
<FontAwesomeIcon icon={faPlay} size="xl" />
|
231 |
)}
|
232 |
</button>
|
233 |
-
<button
|
234 |
-
onClick={handleFastForward}
|
235 |
-
className="control-btn"
|
236 |
-
>
|
237 |
<FontAwesomeIcon icon={faAngleDoubleRight} size="xl" />
|
238 |
</button>
|
239 |
</div>
|
@@ -254,7 +273,10 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
254 |
onChange={handleVolumeChange}
|
255 |
/>
|
256 |
<button onClick={toggleFullscreen} className="control-btn">
|
257 |
-
<FontAwesomeIcon
|
|
|
|
|
|
|
258 |
</button>
|
259 |
{videoUrl && (
|
260 |
<a href={videoUrl} download className="control-btn">
|
@@ -269,7 +291,6 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
269 |
ref={videoRef}
|
270 |
className="video-element"
|
271 |
controls={false}
|
272 |
-
preload="auto"
|
273 |
src={videoUrl}
|
274 |
autoPlay={true}
|
275 |
>
|
@@ -282,7 +303,13 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
282 |
/>
|
283 |
Your browser does not support the video tag.
|
284 |
</video>
|
285 |
-
{isBuffering &&
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
{contextMenu.visible && (
|
287 |
<div
|
288 |
className="context-menu"
|
@@ -295,4 +322,4 @@ export default function MoviePlayer({ videoUrl, title }) {
|
|
295 |
)}
|
296 |
</div>
|
297 |
);
|
298 |
-
}
|
|
|
28 |
const [buffer, setBuffer] = useState(0); // Buffer state
|
29 |
const [isFullscreen, setIsFullscreen] = useState(false);
|
30 |
const [showControls, setShowControls] = useState(true);
|
31 |
+
const [isBuffering, setIsBuffering] = useState(true); // Initialize to true for initial loading
|
32 |
const overlayTimeout = useRef(null);
|
33 |
+
const [contextMenu, setContextMenu] = useState({
|
34 |
+
visible: false,
|
35 |
+
x: 0,
|
36 |
+
y: 0,
|
37 |
+
});
|
38 |
const playerVersion = "0.0.2 Alpha";
|
39 |
|
40 |
useEffect(() => {
|
|
|
49 |
const handleWaiting = () => setIsBuffering(true);
|
50 |
const handlePlaying = () => setIsBuffering(false);
|
51 |
const handleProgress = () => updateBuffer(); // Update buffer on progress
|
52 |
+
const handleLoadedData = () => setIsBuffering(false); // Handle initial data load
|
53 |
+
const handleCanPlayThrough = () => setIsBuffering(false); // Handle when video can play through
|
54 |
|
55 |
videoElement.addEventListener("play", handlePlay);
|
56 |
videoElement.addEventListener("pause", handlePause);
|
|
|
58 |
videoElement.addEventListener("waiting", handleWaiting);
|
59 |
videoElement.addEventListener("playing", handlePlaying);
|
60 |
videoElement.addEventListener("progress", handleProgress); // Listen to progress events
|
61 |
+
videoElement.addEventListener("loadeddata", handleLoadedData); // Listen for initial load
|
62 |
+
videoElement.addEventListener("canplaythrough", handleCanPlayThrough); // Listen for full preload
|
63 |
|
64 |
return () => {
|
65 |
videoElement.removeEventListener("play", handlePlay);
|
|
|
68 |
videoElement.removeEventListener("waiting", handleWaiting);
|
69 |
videoElement.removeEventListener("playing", handlePlaying);
|
70 |
videoElement.removeEventListener("progress", handleProgress); // Clean up progress listener
|
71 |
+
videoElement.removeEventListener("loadeddata", handleLoadedData); // Clean up initial load listener
|
72 |
+
videoElement.removeEventListener("canplaythrough", handleCanPlayThrough); // Clean up full preload listener
|
73 |
};
|
74 |
}, []);
|
75 |
|
|
|
174 |
};
|
175 |
|
176 |
const handleSeek = (newProgress) => {
|
177 |
+
videoRef.current.currentTime =
|
178 |
+
(newProgress / 100) * videoRef.current.duration;
|
179 |
setProgress(newProgress);
|
180 |
};
|
181 |
|
|
|
185 |
|
186 |
const formatTime = (seconds) => {
|
187 |
if (isNaN(seconds)) {
|
188 |
+
return "00:00:00";
|
189 |
}
|
190 |
const wholeSeconds = Math.floor(seconds);
|
191 |
const hours = Math.floor(wholeSeconds / 3600);
|
192 |
const minutes = Math.floor((wholeSeconds % 3600) / 60);
|
193 |
const secs = wholeSeconds % 60;
|
194 |
|
195 |
+
const formattedHours = String(hours).padStart(2, "0");
|
196 |
+
const formattedMinutes = String(minutes).padStart(2, "0");
|
197 |
+
const formattedSeconds = String(secs).padStart(2, "0");
|
198 |
return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
|
199 |
};
|
200 |
|
201 |
const updateBuffer = () => {
|
202 |
const videoElement = videoRef.current;
|
203 |
if (videoElement.buffered.length > 0) {
|
204 |
+
const bufferEnd = videoElement.buffered.end(
|
205 |
+
videoElement.buffered.length - 1
|
206 |
+
);
|
207 |
const bufferValue = (bufferEnd / videoElement.duration) * 100;
|
208 |
setBuffer(bufferValue);
|
209 |
}
|
|
|
214 |
};
|
215 |
|
216 |
return (
|
217 |
+
<div
|
218 |
+
className="video-player-container"
|
219 |
+
onMouseMove={handleMouseMove}
|
220 |
+
onContextMenu={handleContextMenu}
|
221 |
+
>
|
222 |
<div className={`player-overlay ${showControls ? "show" : "hide"}`}>
|
223 |
+
<h2 className="video-title">
|
224 |
+
<div className="control-btn player-exit" onClick={handleExitClick}>
|
225 |
+
<FontAwesomeIcon icon={faArrowLeft} size="lg" />
|
226 |
+
</div>
|
227 |
+
{title}
|
228 |
+
</h2>
|
229 |
<div className="controls">
|
230 |
<div className="player-controls-top">
|
231 |
+
<label className="current-time">
|
232 |
+
{formatTime(videoRef?.current?.currentTime)}
|
233 |
+
</label>
|
234 |
+
<SeekableProgressBar
|
235 |
+
progress={progress}
|
236 |
+
buffer={buffer}
|
237 |
+
onSeek={handleSeek}
|
238 |
+
/>
|
239 |
+
<label className="duration">
|
240 |
+
{formatTime(videoRef?.current?.duration)}
|
241 |
+
</label>
|
242 |
</div>
|
243 |
<div className="player-controls-down">
|
244 |
<div className="player-controls-left">
|
245 |
+
<button onClick={handleRewind} className="control-btn">
|
|
|
|
|
|
|
246 |
<FontAwesomeIcon icon={faAngleDoubleLeft} size="xl" />
|
247 |
</button>
|
248 |
<button onClick={togglePlayPause} className="play-pause-btn">
|
|
|
252 |
<FontAwesomeIcon icon={faPlay} size="xl" />
|
253 |
)}
|
254 |
</button>
|
255 |
+
<button onClick={handleFastForward} className="control-btn">
|
|
|
|
|
|
|
256 |
<FontAwesomeIcon icon={faAngleDoubleRight} size="xl" />
|
257 |
</button>
|
258 |
</div>
|
|
|
273 |
onChange={handleVolumeChange}
|
274 |
/>
|
275 |
<button onClick={toggleFullscreen} className="control-btn">
|
276 |
+
<FontAwesomeIcon
|
277 |
+
icon={isFullscreen ? faCompress : faExpand}
|
278 |
+
size="xl"
|
279 |
+
/>
|
280 |
</button>
|
281 |
{videoUrl && (
|
282 |
<a href={videoUrl} download className="control-btn">
|
|
|
291 |
ref={videoRef}
|
292 |
className="video-element"
|
293 |
controls={false}
|
|
|
294 |
src={videoUrl}
|
295 |
autoPlay={true}
|
296 |
>
|
|
|
303 |
/>
|
304 |
Your browser does not support the video tag.
|
305 |
</video>
|
306 |
+
{isBuffering && (
|
307 |
+
<div className="buffering-indicator">
|
308 |
+
<div className="postion-fix">
|
309 |
+
<Spinner />
|
310 |
+
</div>
|
311 |
+
</div>
|
312 |
+
)}
|
313 |
{contextMenu.visible && (
|
314 |
<div
|
315 |
className="context-menu"
|
|
|
322 |
)}
|
323 |
</div>
|
324 |
);
|
325 |
+
}
|
frontend/src/components/shared/Sidebar/Sidebar.css
CHANGED
@@ -118,6 +118,7 @@
|
|
118 |
font-size: 0.875rem;
|
119 |
font-weight: 500;
|
120 |
margin-left: 10px;
|
|
|
121 |
}
|
122 |
|
123 |
|
|
|
118 |
font-size: 0.875rem;
|
119 |
font-weight: 500;
|
120 |
margin-left: 10px;
|
121 |
+
margin-bottom: 0;
|
122 |
}
|
123 |
|
124 |
|