ChandimaPrabath
commited on
Commit
•
e787e40
1
Parent(s):
7428ad9
movie player test
Browse files
frontend/src/app/genres/[genre]/page.js
CHANGED
@@ -168,7 +168,7 @@ export default function GenrePage({ params }) {
|
|
168 |
{genreItems.series && genreItems.series.length > 0 && (
|
169 |
<section className="section series">
|
170 |
<div className="section-controls">
|
171 |
-
<h2>
|
172 |
<div className="scroll-controls">
|
173 |
<button
|
174 |
onClick={() => scroll(seriesRef, "left")}
|
|
|
168 |
{genreItems.series && genreItems.series.length > 0 && (
|
169 |
<section className="section series">
|
170 |
<div className="section-controls">
|
171 |
+
<h2>TV Shows</h2>
|
172 |
<div className="scroll-controls">
|
173 |
<button
|
174 |
onClick={() => scroll(seriesRef, "left")}
|
frontend/src/app/movie/[title]/page.js
CHANGED
@@ -92,7 +92,7 @@ export default function MovieDetailsPage({ params }) {
|
|
92 |
/>
|
93 |
</div>
|
94 |
<div className="movie-details-actions">
|
95 |
-
<Link href={
|
96 |
<button className="play-button">
|
97 |
<FontAwesomeIcon icon={faPlay} size="lg" /> Play
|
98 |
</button>
|
|
|
92 |
/>
|
93 |
</div>
|
94 |
<div className="movie-details-actions">
|
95 |
+
<Link href={`/player/movie/${params.title}`}>
|
96 |
<button className="play-button">
|
97 |
<FontAwesomeIcon icon={faPlay} size="lg" /> Play
|
98 |
</button>
|
frontend/src/app/movies/filmsPage.css
CHANGED
@@ -1,10 +1,3 @@
|
|
1 |
-
/* Global Styles */
|
2 |
-
body {
|
3 |
-
background-color: #121212;
|
4 |
-
color: #e0e0e0;
|
5 |
-
font-family: Arial, sans-serif;
|
6 |
-
}
|
7 |
-
|
8 |
/* Films Page Container */
|
9 |
.films-page-container {
|
10 |
display: flex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
/* Films Page Container */
|
2 |
.films-page-container {
|
3 |
display: flex;
|
frontend/src/app/player/film/[title]/page.js
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
'use client';
|
2 |
-
|
3 |
-
import { useParams } from 'next/navigation';
|
4 |
-
|
5 |
-
export default function FilmPlayer() {
|
6 |
-
const { title } = useParams();
|
7 |
-
|
8 |
-
return (
|
9 |
-
<>
|
10 |
-
<div>
|
11 |
-
<h1 className='text-white'>Film Player - {title}</h1>
|
12 |
-
{/* Add film player component here */}
|
13 |
-
</div>
|
14 |
-
</>
|
15 |
-
);
|
16 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
frontend/src/app/player/movie/[title]/page.js
ADDED
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use client";
|
2 |
+
import apiClient from "@/api/apiClient";
|
3 |
+
import { useEffect, useState } from "react";
|
4 |
+
|
5 |
+
export default function FilmPlayer({ params }) {
|
6 |
+
const title = decodeURIComponent(params.title);
|
7 |
+
const [videoUrl, setVideoUrl] = useState(null);
|
8 |
+
const [loading, setLoading] = useState(true);
|
9 |
+
const [error, setError] = useState(null);
|
10 |
+
const [downloadProgress, setDownloadProgress] = useState(null);
|
11 |
+
const [downloadProgressUrl, setDownloadProgressUrl] = useState(null);
|
12 |
+
const [metadata, setMetadata] = useState(null);
|
13 |
+
|
14 |
+
useEffect(() => {
|
15 |
+
const fetchMovieCard = async () => {
|
16 |
+
try {
|
17 |
+
const data = await apiClient.getMovieCard(title);
|
18 |
+
if (data.title) {
|
19 |
+
setMetadata(data);
|
20 |
+
} else {
|
21 |
+
setError("Movie card not found");
|
22 |
+
setLoading(false);
|
23 |
+
}
|
24 |
+
} catch (err) {
|
25 |
+
setError("Failed to fetch movie card");
|
26 |
+
setLoading(false);
|
27 |
+
}
|
28 |
+
};
|
29 |
+
|
30 |
+
fetchMovieCard();
|
31 |
+
}, [title]);
|
32 |
+
|
33 |
+
useEffect(() => {
|
34 |
+
if (!metadata) return;
|
35 |
+
|
36 |
+
const fetchVideoData = async () => {
|
37 |
+
try {
|
38 |
+
const data = await apiClient.getMovieByTitle(title);
|
39 |
+
|
40 |
+
if (data.url) {
|
41 |
+
setVideoUrl(data.url);
|
42 |
+
setLoading(false);
|
43 |
+
} else if (data.status === "Download started") {
|
44 |
+
setDownloadProgressUrl(data.progress_url);
|
45 |
+
setLoading(false);
|
46 |
+
}
|
47 |
+
} catch (err) {
|
48 |
+
setError("Failed to fetch video data");
|
49 |
+
setLoading(false);
|
50 |
+
}
|
51 |
+
};
|
52 |
+
|
53 |
+
fetchVideoData();
|
54 |
+
}, [title, metadata]);
|
55 |
+
|
56 |
+
useEffect(() => {
|
57 |
+
if (!downloadProgressUrl) return;
|
58 |
+
|
59 |
+
const intervalId = setInterval(async () => {
|
60 |
+
try {
|
61 |
+
const response = await fetch(downloadProgressUrl);
|
62 |
+
const progressData = await response.json();
|
63 |
+
|
64 |
+
if (progressData.progress.status === "Completed") {
|
65 |
+
clearInterval(intervalId);
|
66 |
+
setDownloadProgressUrl(null);
|
67 |
+
setDownloadProgress(null);
|
68 |
+
setLoading(true);
|
69 |
+
setTimeout(async () => {
|
70 |
+
const data = await apiClient.getMovieByTitle(title);
|
71 |
+
if (data.url) {
|
72 |
+
setVideoUrl(data.url);
|
73 |
+
setLoading(false);
|
74 |
+
}
|
75 |
+
}, 5000); // Wait 5 seconds before fetching the video URL again
|
76 |
+
} else {
|
77 |
+
setDownloadProgress(progressData.progress);
|
78 |
+
}
|
79 |
+
} catch (err) {
|
80 |
+
setError("Failed to fetch download progress");
|
81 |
+
}
|
82 |
+
}, 5000);
|
83 |
+
|
84 |
+
return () => clearInterval(intervalId);
|
85 |
+
}, [downloadProgressUrl, title]);
|
86 |
+
|
87 |
+
return (
|
88 |
+
<div className="film-player-container">
|
89 |
+
{loading && <p className="text-white">Loading...</p>}
|
90 |
+
{error && <p className="text-red-500">{error}</p>}
|
91 |
+
{metadata && !error && (
|
92 |
+
<div className="metadata">
|
93 |
+
<p className="text-white">
|
94 |
+
{metadata.title} ({metadata.year})
|
95 |
+
</p>
|
96 |
+
{metadata.image && (
|
97 |
+
<img
|
98 |
+
src={
|
99 |
+
metadata.banner?.thumbnail
|
100 |
+
? metadata.banner.thumbnail
|
101 |
+
: metadata.image
|
102 |
+
}
|
103 |
+
alt={`${metadata.title} banner`}
|
104 |
+
/>
|
105 |
+
)}
|
106 |
+
</div>
|
107 |
+
)}
|
108 |
+
{downloadProgressUrl && downloadProgress ? (
|
109 |
+
<div className="download-status">
|
110 |
+
<p className="text-yellow-500">
|
111 |
+
{downloadProgress.status} - {downloadProgress.progress.toFixed(2)}%
|
112 |
+
downloaded
|
113 |
+
</p>
|
114 |
+
<p className="text-yellow-500">
|
115 |
+
ETA: {downloadProgress.eta.toFixed(2)} seconds
|
116 |
+
</p>
|
117 |
+
</div>
|
118 |
+
) : (
|
119 |
+
videoUrl && (
|
120 |
+
<div className="video-player">
|
121 |
+
<video controls>
|
122 |
+
<source src={videoUrl} type="video/mp4" />
|
123 |
+
Your browser does not support the video tag.
|
124 |
+
</video>
|
125 |
+
</div>
|
126 |
+
)
|
127 |
+
)}
|
128 |
+
<style jsx>{`
|
129 |
+
.film-player-container {
|
130 |
+
padding: 20px;
|
131 |
+
}
|
132 |
+
.text-white {
|
133 |
+
color: white;
|
134 |
+
}
|
135 |
+
.text-red-500 {
|
136 |
+
color: red;
|
137 |
+
}
|
138 |
+
.text-yellow-500 {
|
139 |
+
color: yellow;
|
140 |
+
}
|
141 |
+
.metadata {
|
142 |
+
margin-bottom: 20px;
|
143 |
+
}
|
144 |
+
.metadata img {
|
145 |
+
max-width: 100%;
|
146 |
+
margin-bottom: 10px;
|
147 |
+
}
|
148 |
+
.video-player {
|
149 |
+
margin-top: 20px;
|
150 |
+
}
|
151 |
+
video {
|
152 |
+
width: 100%;
|
153 |
+
max-width: 800px;
|
154 |
+
}
|
155 |
+
`}</style>
|
156 |
+
</div>
|
157 |
+
);
|
158 |
+
}
|