ChandimaPrabath commited on
Commit
f57be92
·
1 Parent(s): ad5cee0

fix $ improv

Browse files
frontend/src/app/category/[category]/page.js CHANGED
@@ -11,6 +11,7 @@ export default function CategoryPage({ params }) {
11
  const [error, setError] = useState(null);
12
  const [page, setPage] = useState(1);
13
  const [hasMore, setHasMore] = useState(true);
 
14
 
15
  useEffect(() => {
16
  const fetchMusicByCategory = async () => {
@@ -31,8 +32,12 @@ export default function CategoryPage({ params }) {
31
  return [...prevItems, ...newItems];
32
  });
33
 
34
- // Check if there are more files to load based on total_files from the response
35
- setHasMore(musicItems.length + data.files.length < data.total_files); // Update hasMore based on total files
 
 
 
 
36
  } catch (err) {
37
  setError(err.message);
38
  } finally {
@@ -43,7 +48,7 @@ export default function CategoryPage({ params }) {
43
  fetchMusicByCategory();
44
  }, [category, page]);
45
 
46
- // Load more when scrolled to bottom of the app container
47
  useEffect(() => {
48
  const appContainer = document.querySelector('.app-container'); // Get the app-container element
49
  if (!appContainer) return;
@@ -65,7 +70,7 @@ export default function CategoryPage({ params }) {
65
  }, [hasMore, loading]);
66
 
67
  const loadMore = () => {
68
- if (hasMore) {
69
  setPage(prevPage => prevPage + 1);
70
  }
71
  };
 
11
  const [error, setError] = useState(null);
12
  const [page, setPage] = useState(1);
13
  const [hasMore, setHasMore] = useState(true);
14
+ const [maxPage, setMaxPage] = useState(Infinity); // Store the calculated max page
15
 
16
  useEffect(() => {
17
  const fetchMusicByCategory = async () => {
 
32
  return [...prevItems, ...newItems];
33
  });
34
 
35
+ // Calculate maxPage based on total_files and limit, then set it
36
+ const calculatedMaxPage = Math.ceil(data.total_files / data.limit);
37
+ setMaxPage(calculatedMaxPage);
38
+
39
+ // Update hasMore based on whether we have reached maxPage
40
+ setHasMore(page < calculatedMaxPage);
41
  } catch (err) {
42
  setError(err.message);
43
  } finally {
 
48
  fetchMusicByCategory();
49
  }, [category, page]);
50
 
51
+ // Load more when scrolled to the bottom of the app container
52
  useEffect(() => {
53
  const appContainer = document.querySelector('.app-container'); // Get the app-container element
54
  if (!appContainer) return;
 
70
  }, [hasMore, loading]);
71
 
72
  const loadMore = () => {
73
+ if (hasMore && page < maxPage) { // Ensure page does not exceed maxPage
74
  setPage(prevPage => prevPage + 1);
75
  }
76
  };
frontend/src/app/globals.css CHANGED
@@ -3,12 +3,13 @@
3
  @tailwind utilities;
4
 
5
  :root {
6
- --background: #0a0523;
7
  --foreground: #ededed;
8
- --background-secondary: #110652;
9
  --foreground-secondary: #1d85b9;
10
- --background-2: #332a77;
11
- --foreground-2: #0b32a9;
 
12
  }
13
 
14
  html,
 
3
  @tailwind utilities;
4
 
5
  :root {
6
+ --background: #080523;
7
  --foreground: #ededed;
8
+ --background-secondary: #060a52;
9
  --foreground-secondary: #1d85b9;
10
+ --background-2: #2a3477;
11
+ --foreground-2: #0b5da9;
12
+ --foreground-3: #0f0e60;
13
  }
14
 
15
  html,
frontend/src/components/Card.css CHANGED
@@ -1,7 +1,7 @@
1
  .music-card {
2
  width: 250px;
3
  height: 40;
4
- background-image: linear-gradient(var(--background-2), var(--foreground-2));
5
  border-top-left-radius: 20px;
6
  border-bottom-left-radius: 20px;
7
  border-top-right-radius: 5px;
@@ -10,6 +10,7 @@
10
  align-items: center;
11
  gap: 10px;
12
  overflow: hidden;
 
13
  }
14
 
15
  .card-title {
@@ -27,3 +28,30 @@
27
  font-size: 40px;
28
  overflow: visible;
29
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  .music-card {
2
  width: 250px;
3
  height: 40;
4
+ background-image: linear-gradient(var(--background-2), var(--foreground-3));
5
  border-top-left-radius: 20px;
6
  border-bottom-left-radius: 20px;
7
  border-top-right-radius: 5px;
 
10
  align-items: center;
11
  gap: 10px;
12
  overflow: hidden;
13
+ transition: scale .3s ease;
14
  }
15
 
16
  .card-title {
 
28
  font-size: 40px;
29
  overflow: visible;
30
  }
31
+
32
+ .music-card:hover{
33
+ scale: 1.03;
34
+ }
35
+
36
+ .music-card.music-card.now-playing{
37
+ background-image: linear-gradient(var(--background-2), var(--foreground-2));
38
+ border: 2px solid var(--foreground-secondary);
39
+ border-right: none;
40
+ border-bottom: none;
41
+ border-left: none;
42
+ box-shadow: 0 0 15px var(--foreground-secondary);
43
+ scale: 1.03;
44
+ }
45
+
46
+ .music-card.now-playing .card-icon{
47
+ animation: rotateInfinite 1.5s linear infinite;
48
+ }
49
+
50
+ @keyframes rotateInfinite {
51
+ 0% {
52
+ transform: rotateZ(0deg);
53
+ }
54
+ 100% {
55
+ transform: rotateZ(360deg);
56
+ }
57
+ }
frontend/src/components/Card.js CHANGED
@@ -2,20 +2,19 @@
2
  import "./Card.css";
3
  import { FaCompactDisc } from "react-icons/fa";
4
  import { useMusicPlayer } from "@/context/MusicPlayerContext";
 
5
 
6
  const Card = ({ src }) => {
7
- const { initializePlayer } = useMusicPlayer();
8
-
9
- // Extract title from the src by parsing the file name
10
- const title = src.split('/').pop().split('.')[0]; // Remove path and extension
11
 
12
  const handleButtonClick = () => {
13
- initializePlayer(src);
14
  };
15
 
16
  return (
17
  <button onClick={handleButtonClick}>
18
- <div className="music-card">
19
  <FaCompactDisc className="card-icon" />
20
  <label className="card-title">{title}</label>
21
  </div>
 
2
  import "./Card.css";
3
  import { FaCompactDisc } from "react-icons/fa";
4
  import { useMusicPlayer } from "@/context/MusicPlayerContext";
5
+ import { formatTitle } from "@/lib/utils";
6
 
7
  const Card = ({ src }) => {
8
+ const { initializePlayer, nowPlaying } = useMusicPlayer();
9
+ const title = formatTitle(src);
 
 
10
 
11
  const handleButtonClick = () => {
12
+ initializePlayer(src, title);
13
  };
14
 
15
  return (
16
  <button onClick={handleButtonClick}>
17
+ <div className={`music-card ${nowPlaying === title ? "now-playing" : ""}`}>
18
  <FaCompactDisc className="card-icon" />
19
  <label className="card-title">{title}</label>
20
  </div>
frontend/src/components/MusicPlayer.js CHANGED
@@ -26,9 +26,13 @@ export default function MusicPlayer() {
26
  togglePlayerSize,
27
  setIsPlayerVisible,
28
  initializePlayer,
29
- fileName,
 
 
 
 
30
  } = useMusicPlayer();
31
-
32
  const [currentSrc, setCurrentSrc] = useState(src);
33
  const [currentTime, setCurrentTime] = useState(0);
34
  const [duration, setDuration] = useState(0);
@@ -42,69 +46,79 @@ export default function MusicPlayer() {
42
  const [isFullscreen, setIsFullscreen] = useState(false);
43
  const overlayTimeout = useRef(null);
44
  const seekTime = 5;
45
-
46
- useEffect(() => {
47
- if (!currentSrc) return;
48
-
49
- const videoElement = videoRef.current;
50
-
51
- const handleTimeUpdate = () => {
52
- if (videoElement) {
53
- setCurrentTime(videoElement.currentTime);
54
- setProgress((videoElement.currentTime / videoElement.duration) * 100);
55
- }
56
- };
57
-
58
- const handleLoadedMetadata = () => {
59
- if (videoElement) {
60
- setDuration(videoElement.duration);
61
- setProgress(0);
62
- setCurrentTime(0);
63
- }
64
- };
65
-
66
- const handleProgress = () => {
67
- const videoElement = videoRef.current;
68
- if (videoElement.buffered.length > 0) {
69
- const bufferEnd = videoElement.buffered.end(
70
- videoElement.buffered.length - 1
71
- );
72
- const bufferValue = (bufferEnd / videoElement.duration) * 100;
73
- setBufferProgress(bufferValue);
74
- }
75
- };
76
-
77
- const handlePlay = () => setIsPlaying(true);
78
- const handlePause = () => setIsPlaying(false);
79
-
 
80
  if (videoElement) {
81
- videoElement.addEventListener("timeupdate", handleTimeUpdate);
82
- videoElement.addEventListener("loadedmetadata", handleLoadedMetadata);
83
- videoElement.addEventListener("progress", handleProgress);
84
  videoElement.addEventListener("play", handlePlay);
85
  videoElement.addEventListener("pause", handlePause);
86
  }
87
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  return () => {
89
- if (videoElement) {
90
- videoElement.removeEventListener("timeupdate", handleTimeUpdate);
91
- videoElement.removeEventListener(
92
- "loadedmetadata",
93
- handleLoadedMetadata
94
- );
95
- videoElement.removeEventListener("progress", handleProgress);
96
- videoElement.removeEventListener("play", handlePlay);
97
- videoElement.removeEventListener("pause", handlePause);
98
- }
99
  };
100
- }, [videoRef, currentSrc]);
101
-
102
  useEffect(() => {
103
  if (src !== currentSrc) {
104
  setCurrentSrc(src);
105
  }
106
  }, [src, currentSrc]);
107
-
108
  useEffect(() => {
109
  if (showControls) {
110
  if (overlayTimeout.current) {
@@ -112,10 +126,10 @@ export default function MusicPlayer() {
112
  }
113
  overlayTimeout.current = setTimeout(() => setShowControls(false), 3000);
114
  }
115
-
116
  return () => clearTimeout(overlayTimeout.current);
117
  }, [showControls]);
118
-
119
  const togglePlayPause = () => {
120
  if (videoRef.current) {
121
  if (isPlaying) {
@@ -126,23 +140,20 @@ export default function MusicPlayer() {
126
  setIsPlaying(!isPlaying);
127
  }
128
  };
 
129
  const handleVolumeChange = (event) => {
130
  let volumeValue = parseFloat(event.target.value);
131
-
132
  // Ensure the volume is a finite number between 0 and 1
133
- if (!isFinite(volumeValue) || volumeValue < 0) {
134
- volumeValue = 0;
135
- } else if (volumeValue > 1) {
136
- volumeValue = 1;
137
- }
138
-
139
  setVolume(volumeValue);
140
  if (videoRef.current) {
141
  videoRef.current.volume = volumeValue;
142
  }
143
  setIsMuted(volumeValue === 0);
144
  };
145
-
146
  const toggleMute = () => {
147
  if (isMuted) {
148
  videoRef.current.volume = volume;
@@ -152,38 +163,50 @@ export default function MusicPlayer() {
152
  setIsMuted(true);
153
  }
154
  };
155
-
156
  const toggleFullscreen = () => {
157
  const doc = window.document;
158
  const docEl = doc.documentElement;
159
-
160
  const requestFullscreen =
161
  docEl.requestFullscreen ||
162
  docEl.mozRequestFullScreen ||
163
  docEl.webkitRequestFullscreen ||
164
  docEl.msRequestFullscreen;
 
165
  const exitFullscreen =
166
  doc.exitFullscreen ||
167
  doc.mozCancelFullScreen ||
168
  docEl.webkitExitFullscreen ||
169
  doc.msExitFullscreen;
170
-
171
  if (!isFullscreen) {
172
  requestFullscreen.call(docEl);
173
  } else {
174
  exitFullscreen.call(doc);
175
  }
176
-
177
  setIsFullscreen(!isFullscreen);
178
  };
179
-
180
  const destroyPlayer = () => {
181
  if (videoRef.current) {
182
- videoRef.current.src = "";
 
 
 
 
 
 
 
 
 
183
  setIsPlayerVisible(false);
 
 
184
  }
185
  };
186
-
187
  const handleProgressClick = (e) => {
188
  const progressBar = e.currentTarget;
189
  const rect = progressBar.getBoundingClientRect();
@@ -194,7 +217,7 @@ export default function MusicPlayer() {
194
  setCurrentTime(newTime);
195
  }
196
  };
197
-
198
  const handleFastForward = () => {
199
  if (videoRef.current) {
200
  videoRef.current.currentTime = Math.min(
@@ -203,7 +226,7 @@ export default function MusicPlayer() {
203
  );
204
  }
205
  };
206
-
207
  const handleRewind = () => {
208
  if (videoRef.current) {
209
  videoRef.current.currentTime = Math.max(
@@ -212,11 +235,13 @@ export default function MusicPlayer() {
212
  );
213
  }
214
  };
 
215
  const handleMouseMove = () => {
216
  setShowControls(true);
217
  };
 
218
  if (!isPlayerVisible || !currentSrc) return null;
219
-
220
  return (
221
  <div
222
  className={
@@ -230,7 +255,7 @@ export default function MusicPlayer() {
230
  <div className={`player-controls ${showControls ? "show" : "hide"}`}>
231
  <div className="player-controls-top">
232
  <div className="name-container">
233
- <label className="music-title">{fileName}</label>
234
  <button className="player-max-button" onClick={togglePlayerSize}>
235
  <IoIosArrowDown />
236
  </button>
@@ -339,7 +364,7 @@ export default function MusicPlayer() {
339
  {!isPlayerMaximized && (
340
  <div className="player-controls-mini">
341
  <div className="player-mini-control-top">
342
- <label className="music-title player-mini">{fileName}</label>
343
  <button className="player-min-button" onClick={togglePlayerSize}>
344
  <IoIosArrowUp />
345
  </button>
 
26
  togglePlayerSize,
27
  setIsPlayerVisible,
28
  initializePlayer,
29
+ title,
30
+ setNowPlaying,
31
+ nowPlaying,
32
+ didDestroy,
33
+ setDidDestroy,
34
  } = useMusicPlayer();
35
+
36
  const [currentSrc, setCurrentSrc] = useState(src);
37
  const [currentTime, setCurrentTime] = useState(0);
38
  const [duration, setDuration] = useState(0);
 
46
  const [isFullscreen, setIsFullscreen] = useState(false);
47
  const overlayTimeout = useRef(null);
48
  const seekTime = 5;
49
+
50
+ // Event Handlers
51
+ const handleTimeUpdate = (videoElement) => {
52
+ if (videoElement) {
53
+ setCurrentTime(videoElement.currentTime);
54
+ setProgress((videoElement.currentTime / videoElement.duration) * 100);
55
+ }
56
+ };
57
+
58
+ const handleLoadedMetadata = (videoElement) => {
59
+ if (videoElement) {
60
+ setDuration(videoElement.duration);
61
+ setProgress(0);
62
+ setCurrentTime(0);
63
+ }
64
+ };
65
+
66
+ const handleProgress = (videoElement) => {
67
+ if (videoElement && videoElement.buffered.length > 0) {
68
+ const bufferEnd = videoElement.buffered.end(videoElement.buffered.length - 1);
69
+ const bufferValue = (bufferEnd / videoElement.duration) * 100;
70
+ setBufferProgress(bufferValue);
71
+ }
72
+ };
73
+
74
+ const handlePlay = () => {
75
+ setIsPlaying(true);
76
+ setNowPlaying(title);
77
+ };
78
+
79
+ const handlePause = () => {
80
+ setIsPlaying(false);
81
+ setNowPlaying("");
82
+ };
83
+
84
+ const attachEventListeners = (videoElement) => {
85
  if (videoElement) {
86
+ videoElement.addEventListener("timeupdate", () => handleTimeUpdate(videoElement));
87
+ videoElement.addEventListener("loadedmetadata", () => handleLoadedMetadata(videoElement));
88
+ videoElement.addEventListener("progress", () => handleProgress(videoElement));
89
  videoElement.addEventListener("play", handlePlay);
90
  videoElement.addEventListener("pause", handlePause);
91
  }
92
+ };
93
+
94
+ const detachEventListeners = (videoElement) => {
95
+ if (videoElement) {
96
+ videoElement.removeEventListener("timeupdate", () => handleTimeUpdate(videoElement));
97
+ videoElement.removeEventListener("loadedmetadata", () => handleLoadedMetadata(videoElement));
98
+ videoElement.removeEventListener("progress", () => handleProgress(videoElement));
99
+ videoElement.removeEventListener("play", handlePlay);
100
+ videoElement.removeEventListener("pause", handlePause);
101
+ }
102
+ };
103
+
104
+ useEffect(() => {
105
+ const videoElement = videoRef.current;
106
+
107
+ // Attach event listeners
108
+ attachEventListeners(videoElement);
109
+
110
  return () => {
111
+ // Detach event listeners
112
+ detachEventListeners(videoElement);
 
 
 
 
 
 
 
 
113
  };
114
+ }, [videoRef, currentSrc, nowPlaying, didDestroy]);
115
+
116
  useEffect(() => {
117
  if (src !== currentSrc) {
118
  setCurrentSrc(src);
119
  }
120
  }, [src, currentSrc]);
121
+
122
  useEffect(() => {
123
  if (showControls) {
124
  if (overlayTimeout.current) {
 
126
  }
127
  overlayTimeout.current = setTimeout(() => setShowControls(false), 3000);
128
  }
129
+
130
  return () => clearTimeout(overlayTimeout.current);
131
  }, [showControls]);
132
+
133
  const togglePlayPause = () => {
134
  if (videoRef.current) {
135
  if (isPlaying) {
 
140
  setIsPlaying(!isPlaying);
141
  }
142
  };
143
+
144
  const handleVolumeChange = (event) => {
145
  let volumeValue = parseFloat(event.target.value);
146
+
147
  // Ensure the volume is a finite number between 0 and 1
148
+ volumeValue = Math.max(0, Math.min(1, volumeValue));
149
+
 
 
 
 
150
  setVolume(volumeValue);
151
  if (videoRef.current) {
152
  videoRef.current.volume = volumeValue;
153
  }
154
  setIsMuted(volumeValue === 0);
155
  };
156
+
157
  const toggleMute = () => {
158
  if (isMuted) {
159
  videoRef.current.volume = volume;
 
163
  setIsMuted(true);
164
  }
165
  };
166
+
167
  const toggleFullscreen = () => {
168
  const doc = window.document;
169
  const docEl = doc.documentElement;
170
+
171
  const requestFullscreen =
172
  docEl.requestFullscreen ||
173
  docEl.mozRequestFullScreen ||
174
  docEl.webkitRequestFullscreen ||
175
  docEl.msRequestFullscreen;
176
+
177
  const exitFullscreen =
178
  doc.exitFullscreen ||
179
  doc.mozCancelFullScreen ||
180
  docEl.webkitExitFullscreen ||
181
  doc.msExitFullscreen;
182
+
183
  if (!isFullscreen) {
184
  requestFullscreen.call(docEl);
185
  } else {
186
  exitFullscreen.call(doc);
187
  }
188
+
189
  setIsFullscreen(!isFullscreen);
190
  };
191
+
192
  const destroyPlayer = () => {
193
  if (videoRef.current) {
194
+ videoRef.current.pause();
195
+ videoRef.current.removeAttribute("src"); // Clear the source
196
+ videoRef.current.load(); // Reload to reset duration/currentTime
197
+ setNowPlaying("");
198
+ setCurrentSrc("/reset");
199
+ setCurrentTime(0);
200
+ setDuration(0);
201
+ setProgress(0);
202
+ setBufferProgress(0);
203
+ setIsPlaying(false);
204
  setIsPlayerVisible(false);
205
+ setDidDestroy(true);
206
+ console.log("setting didDestroy to true");
207
  }
208
  };
209
+
210
  const handleProgressClick = (e) => {
211
  const progressBar = e.currentTarget;
212
  const rect = progressBar.getBoundingClientRect();
 
217
  setCurrentTime(newTime);
218
  }
219
  };
220
+
221
  const handleFastForward = () => {
222
  if (videoRef.current) {
223
  videoRef.current.currentTime = Math.min(
 
226
  );
227
  }
228
  };
229
+
230
  const handleRewind = () => {
231
  if (videoRef.current) {
232
  videoRef.current.currentTime = Math.max(
 
235
  );
236
  }
237
  };
238
+
239
  const handleMouseMove = () => {
240
  setShowControls(true);
241
  };
242
+
243
  if (!isPlayerVisible || !currentSrc) return null;
244
+
245
  return (
246
  <div
247
  className={
 
255
  <div className={`player-controls ${showControls ? "show" : "hide"}`}>
256
  <div className="player-controls-top">
257
  <div className="name-container">
258
+ <label className="music-title">{title}</label>
259
  <button className="player-max-button" onClick={togglePlayerSize}>
260
  <IoIosArrowDown />
261
  </button>
 
364
  {!isPlayerMaximized && (
365
  <div className="player-controls-mini">
366
  <div className="player-mini-control-top">
367
+ <label className="music-title player-mini">{title}</label>
368
  <button className="player-min-button" onClick={togglePlayerSize}>
369
  <IoIosArrowUp />
370
  </button>
frontend/src/context/MusicPlayerContext.js CHANGED
@@ -1,52 +1,47 @@
1
- "use client";
2
-
3
- import React, { createContext, useContext, useRef, useState } from "react";
4
 
5
  const MusicPlayerContext = createContext();
6
 
7
  export const MusicPlayerProvider = ({ children }) => {
8
  const videoRef = useRef(null);
9
  const [src, setSrc] = useState("");
10
- const [fileName, setFileName] = useState("");
 
11
  const [isPlayerVisible, setIsPlayerVisible] = useState(false);
12
  const [isPlayerMaximized, setIsPlayerMaximized] = useState(false);
13
  const [loadingProgress, setLoadingProgress] = useState(null);
14
  const [abortController, setAbortController] = useState(null); // AbortController for stopping
 
15
 
16
- const initializePlayer = async (source) => {
17
- // Stop any ongoing initializePlayer process if called again
18
  if (abortController) {
19
- abortController.abort(); // Cancel the previous request
20
  }
21
-
22
- // Set up a new AbortController
23
  const newAbortController = new AbortController();
24
  setAbortController(newAbortController);
25
 
26
- // Extract the file name and start the player
27
  const extractedFileName = source.split('/').pop();
28
- setFileName(extractedFileName);
29
- if (videoRef.current){
30
  videoRef.current.pause();
31
  }
32
 
33
  try {
34
- // Call the API with the signal to allow aborting
35
  const response = await fetch(`/api/get/music/${encodeURIComponent(extractedFileName)}`, {
36
  signal: newAbortController.signal,
37
  });
38
  const data = await response.json();
39
 
40
- // If the file is being downloaded, check progress
41
  if (data.status === "Download started") {
42
  const progressUrl = data.progress_url;
43
  checkProgress(progressUrl, extractedFileName, newAbortController);
44
  } else {
45
- startPlayer(data.url); // Start the player with the final URL if available
46
  }
47
  } catch (error) {
48
  if (error.name !== 'AbortError') {
49
- console.error("Error initializing player:", error); // Log only non-abort errors
50
  }
51
  }
52
  };
@@ -56,7 +51,6 @@ export const MusicPlayerProvider = ({ children }) => {
56
  try {
57
  const response = await fetch(progressUrl, { signal: abortController.signal });
58
  const progressData = await response.json();
59
-
60
  setLoadingProgress(progressData.progress);
61
 
62
  if (progressData.progress.status === "Completed") {
@@ -65,7 +59,7 @@ export const MusicPlayerProvider = ({ children }) => {
65
  }
66
  } catch (error) {
67
  if (error.name === 'AbortError') {
68
- clearInterval(intervalId); // Stop checking progress if aborted
69
  } else {
70
  console.error("Error fetching progress:", error);
71
  }
@@ -83,32 +77,35 @@ export const MusicPlayerProvider = ({ children }) => {
83
  if (data.url) {
84
  startPlayer(data.url);
85
  } else {
86
- // Retry after a delay if the URL is not available
87
  retryFetchFinalUrl(fileName, abortController, attempt);
88
  }
89
  } catch (error) {
90
  if (error.name !== 'AbortError') {
91
  console.error("Error fetching final URL:", error);
92
- // Retry after a delay if any error occurs
93
  retryFetchFinalUrl(fileName, abortController, attempt);
94
  }
95
  }
96
  };
97
 
98
  const retryFetchFinalUrl = (fileName, abortController, attempt) => {
99
- const retryDelay = 2000; // Delay before retrying
100
  setTimeout(() => {
101
  console.log(`Retry attempt ${attempt} for ${fileName}`);
102
- fetchFinalUrl(fileName, abortController, attempt + 1); // Increment the attempt count
103
  }, retryDelay);
104
  };
105
 
106
  const startPlayer = (source) => {
 
 
107
  setSrc(source);
108
  setIsPlayerVisible(true);
109
  if (videoRef.current) {
110
  videoRef.current.src = source;
111
  videoRef.current.load();
 
 
 
112
  }
113
  };
114
 
@@ -121,11 +118,15 @@ export const MusicPlayerProvider = ({ children }) => {
121
  initializePlayer,
122
  isPlayerVisible,
123
  src,
124
- fileName,
125
  isPlayerMaximized,
126
  togglePlayerSize,
127
  setIsPlayerVisible,
128
  loadingProgress,
 
 
 
 
129
  }}
130
  >
131
  {children}
 
1
+ import React, { createContext, useContext, useRef, useState, useEffect } from "react";
 
 
2
 
3
  const MusicPlayerContext = createContext();
4
 
5
  export const MusicPlayerProvider = ({ children }) => {
6
  const videoRef = useRef(null);
7
  const [src, setSrc] = useState("");
8
+ const [title, setTitle] = useState("");
9
+ const [nowPlaying, setNowPlaying] = useState("");
10
  const [isPlayerVisible, setIsPlayerVisible] = useState(false);
11
  const [isPlayerMaximized, setIsPlayerMaximized] = useState(false);
12
  const [loadingProgress, setLoadingProgress] = useState(null);
13
  const [abortController, setAbortController] = useState(null); // AbortController for stopping
14
+ const [didDestroy, setDidDestroy] = useState(false);
15
 
16
+ const initializePlayer = async (source, title) => {
 
17
  if (abortController) {
18
+ abortController.abort();
19
  }
20
+
 
21
  const newAbortController = new AbortController();
22
  setAbortController(newAbortController);
23
 
 
24
  const extractedFileName = source.split('/').pop();
25
+ setTitle(title);
26
+ if (videoRef.current) {
27
  videoRef.current.pause();
28
  }
29
 
30
  try {
 
31
  const response = await fetch(`/api/get/music/${encodeURIComponent(extractedFileName)}`, {
32
  signal: newAbortController.signal,
33
  });
34
  const data = await response.json();
35
 
 
36
  if (data.status === "Download started") {
37
  const progressUrl = data.progress_url;
38
  checkProgress(progressUrl, extractedFileName, newAbortController);
39
  } else {
40
+ startPlayer(data.url);
41
  }
42
  } catch (error) {
43
  if (error.name !== 'AbortError') {
44
+ console.error("Error initializing player:", error);
45
  }
46
  }
47
  };
 
51
  try {
52
  const response = await fetch(progressUrl, { signal: abortController.signal });
53
  const progressData = await response.json();
 
54
  setLoadingProgress(progressData.progress);
55
 
56
  if (progressData.progress.status === "Completed") {
 
59
  }
60
  } catch (error) {
61
  if (error.name === 'AbortError') {
62
+ clearInterval(intervalId);
63
  } else {
64
  console.error("Error fetching progress:", error);
65
  }
 
77
  if (data.url) {
78
  startPlayer(data.url);
79
  } else {
 
80
  retryFetchFinalUrl(fileName, abortController, attempt);
81
  }
82
  } catch (error) {
83
  if (error.name !== 'AbortError') {
84
  console.error("Error fetching final URL:", error);
 
85
  retryFetchFinalUrl(fileName, abortController, attempt);
86
  }
87
  }
88
  };
89
 
90
  const retryFetchFinalUrl = (fileName, abortController, attempt) => {
91
+ const retryDelay = 2000;
92
  setTimeout(() => {
93
  console.log(`Retry attempt ${attempt} for ${fileName}`);
94
+ fetchFinalUrl(fileName, abortController, attempt + 1);
95
  }, retryDelay);
96
  };
97
 
98
  const startPlayer = (source) => {
99
+ setDidDestroy(false);
100
+ console.log("setting didDestroy to false");
101
  setSrc(source);
102
  setIsPlayerVisible(true);
103
  if (videoRef.current) {
104
  videoRef.current.src = source;
105
  videoRef.current.load();
106
+ videoRef.current.play().catch((error) => {
107
+ console.error("Error playing video:", error);
108
+ });
109
  }
110
  };
111
 
 
118
  initializePlayer,
119
  isPlayerVisible,
120
  src,
121
+ title,
122
  isPlayerMaximized,
123
  togglePlayerSize,
124
  setIsPlayerVisible,
125
  loadingProgress,
126
+ nowPlaying,
127
+ setNowPlaying,
128
+ didDestroy,
129
+ setDidDestroy,
130
  }}
131
  >
132
  {children}
frontend/src/lib/utils.js ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ export function formatTitle(src){
2
+ return src.split('/').pop().split('.')[0];
3
+ }