diff --git a/public/index.html b/public/index.html index db0f047..5c7323b 100644 --- a/public/index.html +++ b/public/index.html @@ -265,6 +265,7 @@
+
diff --git a/public/script/downloadstatus.js b/public/script/downloadstatus.js index 868ac9c..140d217 100644 --- a/public/script/downloadstatus.js +++ b/public/script/downloadstatus.js @@ -118,4 +118,7 @@ function resetProgressBar() { const speedElement = document.getElementById("downloadSpeedText"); if (speedElement) speedElement.style.display = "none"; + + const playlistInfoElement = document.getElementById("playlistInfoText"); + if (playlistInfoElement) playlistInfoElement.style.display = "none"; } \ No newline at end of file diff --git a/public/script/progressBar.js b/public/script/progressBar.js index 681315c..4b8e5ce 100644 --- a/public/script/progressBar.js +++ b/public/script/progressBar.js @@ -4,8 +4,10 @@ const progressBarText = document.getElementById("downloadProgressText") const speedElement = document.getElementById("downloadSpeedText"); const stageElement = document.getElementById("downloadStage"); +const playlistInfoElement = document.getElementById("playlistInfoText"); const speedEvt = new EventSource("/download/speed"); const stageEvt = new EventSource("/download/stage"); +const playlistInfoEvt = new EventSource("/download/playlist-info"); function startProgress() { progressBar.style.width = "0%"; @@ -45,6 +47,9 @@ function resetProgress() { stageElement.textContent = ""; stageElement.style.display = "none"; + playlistInfoElement.textContent = ""; + playlistInfoElement.style.display = "none"; + // Hide stop button const stopBtn = document.getElementById("stopBtn"); if (stopBtn) stopBtn.style.display = "none"; @@ -85,4 +90,9 @@ speedEvt.onmessage = e => { stageEvt.onmessage = e => { stageElement.style.display = "block"; stageElement.textContent = e.data; // ex: "📥 Downloading..." +}; + +playlistInfoEvt.onmessage = e => { + playlistInfoElement.style.display = "block"; + playlistInfoElement.textContent = e.data; // ex: "Item 1 of 15" }; \ No newline at end of file diff --git a/server/controller/download.controller.js b/server/controller/download.controller.js index b87ab33..c586e21 100644 --- a/server/controller/download.controller.js +++ b/server/controller/download.controller.js @@ -6,6 +6,7 @@ const { notifyDownloadFinished } = require("../helpers/notify.helpers"); const listeners = []; const speedListeners = []; const stageListeners = []; +const playlistInfoListeners = []; async function downloadController(req, res) { try { @@ -24,7 +25,7 @@ async function downloadController(req, res) { } // Get output folder when the download is finished - const outputFolder = await fetchDownload(options, listeners, speedListeners, stageListeners); + const outputFolder = await fetchDownload(options, listeners, speedListeners, stageListeners, playlistInfoListeners); notifyDownloadFinished(outputFolder); res.send("Download Done !"); @@ -93,4 +94,20 @@ function cancelDownloadController(req, res) { } } -module.exports = { downloadController, progressController, speedController, stageController, cancelDownloadController}; +function playlistInfoController(req, res) { + res.set({ + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache', + 'Connection': 'keep-alive', + }); + + const sendPlaylistInfo = info => res.write(`data: ${info}\n\n`); + playlistInfoListeners.push(sendPlaylistInfo); + + req.on('close', () => { + playlistInfoListeners.splice(playlistInfoListeners.indexOf(sendPlaylistInfo), 1); + res.end(); + }); +} + +module.exports = { downloadController, progressController, speedController, stageController, cancelDownloadController, playlistInfoController}; diff --git a/server/routes/download.route.js b/server/routes/download.route.js index 5310285..1d814f6 100644 --- a/server/routes/download.route.js +++ b/server/routes/download.route.js @@ -1,6 +1,6 @@ const express = require("express"); const router = express.Router(); -const { downloadController, progressController, speedController, stageController, cancelDownloadController } = require("../controller/download.controller"); +const { downloadController, progressController, speedController, stageController, cancelDownloadController, playlistInfoController } = require("../controller/download.controller"); router.post("/", downloadController); router.post("/cancel", cancelDownloadController); @@ -9,5 +9,6 @@ router.post("/cancel", cancelDownloadController); router.get("/progress", progressController); router.get("/speed", speedController); router.get("/stage", stageController); +router.get("/playlist-info", playlistInfoController); module.exports = router; \ No newline at end of file diff --git a/server/services/download.services.js b/server/services/download.services.js index b36e6f1..b80d176 100644 --- a/server/services/download.services.js +++ b/server/services/download.services.js @@ -74,7 +74,7 @@ function createPlaylistFolder(basePath, playlistTitle) { } } -function fetchDownload(options, listeners, speedListeners, stageListeners) { +function fetchDownload(options, listeners, speedListeners, stageListeners, playlistInfoListeners) { return new Promise((resolve, reject) => { logger.info(`CONFIG createPlaylistFolders: ${configFeatures.createPlaylistFolders}`); @@ -152,6 +152,13 @@ function fetchDownload(options, listeners, speedListeners, stageListeners) { } } + // Playlist item tracking + const itemMatch = line.match(/Downloading\s+(?:item|video)?\s*(\d+)\s+of\s+(\d+)/i); + if (itemMatch) { + const itemInfo = `Item ${itemMatch[1]} of ${itemMatch[2]}`; + playlistInfoListeners.forEach(fn => fn(itemInfo)); + } + // Stage messages if (line.includes("[Merger]")) { stageListeners.forEach(fn => fn("Merging formats..."));