This commit is contained in:
2025-12-10 07:24:25 +00:00
parent ac999dda59
commit 8a1cf6129d
2 changed files with 59 additions and 15 deletions

View File

@@ -71,6 +71,11 @@ class DownloadManager:
def add_to_queue(self, item_type: str, item_id: str): def add_to_queue(self, item_type: str, item_id: str):
task_id = f"{item_type}_{item_id}" task_id = f"{item_type}_{item_id}"
# Prevent duplicate tasks
if task_id in self.active_downloads:
return self.active_downloads[task_id]
task = { task = {
"id": task_id, "id": task_id,
"type": item_type, "type": item_type,
@@ -93,19 +98,28 @@ class DownloadManager:
break break
task_id = task["id"] task_id = task["id"]
self.active_downloads[task_id]["status"] = "downloading"
# Ensure task is tracked in active_downloads
if task_id not in self.active_downloads:
self.active_downloads[task_id] = task
task["status"] = "downloading"
try: try:
self._process_download(task) self._process_download(task)
self.active_downloads[task_id]["status"] = "completed" task["status"] = "completed"
self.active_downloads[task_id]["progress"] = 100 task["progress"] = 100
except Exception as e: except Exception as e:
logger.error(f"Download failed: {e}") logger.error(f"Download failed: {e}")
self.active_downloads[task_id]["status"] = "failed" task["status"] = "failed"
self.active_downloads[task_id]["error"] = str(e) task["error"] = str(e)
finally: finally:
# Move to history # Move to history
self.history.append(self.active_downloads.pop(task_id)) # Only pop if the current task in active_downloads is the one we just processed
if task_id in self.active_downloads and self.active_downloads[task_id] is task:
self.history.append(self.active_downloads.pop(task_id))
else:
self.history.append(task)
self.queue.task_done() self.queue.task_done()
def cancel_task(self, task_id: str): def cancel_task(self, task_id: str):
@@ -158,14 +172,14 @@ class DownloadManager:
if key == "progress": if key == "progress":
# For single track, this is the main progress # For single track, this is the main progress
if task["type"] == "track": if task["type"] == "track":
self.active_downloads[task["id"]]["progress"] = value task["progress"] = value
elif key == "name": elif key == "name":
# Update status with current track name # Update status with current track name
self.active_downloads[task["id"]]["current_item"] = value task["current_item"] = value
elif key == "list_progress": elif key == "list_progress":
# For albums/playlists, this is the main progress # For albums/playlists, this is the main progress
if task["type"] != "track": if task["type"] != "track":
self.active_downloads[task["id"]]["progress"] = value task["progress"] = value
mock_progress = MockProgressBars(update_task) mock_progress = MockProgressBars(update_task)

View File

@@ -29,8 +29,15 @@
</div> </div>
<div class="card"> <div class="card">
<h2>Download Queue</h2> <h2>Downloads</h2>
<div id="queue-list"></div> <details open>
<summary>Active Queue <span id="queue-count"></span></summary>
<div id="queue-list"></div>
</details>
<details>
<summary>History <span id="history-count"></span></summary>
<div id="history-list"></div>
</details>
</div> </div>
</div> </div>
@@ -171,20 +178,35 @@
const response = await fetch('/download/queue'); const response = await fetch('/download/queue');
const queue = await response.json(); const queue = await response.json();
const list = document.getElementById('queue-list'); const queueList = document.getElementById('queue-list');
list.innerHTML = ''; const historyList = document.getElementById('history-list');
queueList.innerHTML = '';
historyList.innerHTML = '';
let activeCount = 0;
let historyCount = 0;
queue.forEach(item => { queue.forEach(item => {
const div = document.createElement('div'); const div = document.createElement('div');
div.className = 'queue-item'; div.className = 'queue-item';
let controls = ''; let controls = '';
if (item.status === 'downloading' || item.status === 'queued') {
// Determine if active or history
// Active: queued, downloading
// History: completed, failed, cancelled
const isHistory = ['completed', 'failed', 'cancelled'].includes(item.status);
if (!isHistory) {
activeCount++;
if (item.control === 'pause') { if (item.control === 'pause') {
controls += `<button onclick="controlTask('${item.id}', 'resume')">Resume</button>`; controls += `<button onclick="controlTask('${item.id}', 'resume')">Resume</button>`;
} else { } else {
controls += `<button onclick="controlTask('${item.id}', 'pause')">Pause</button>`; controls += `<button onclick="controlTask('${item.id}', 'pause')">Pause</button>`;
} }
controls += `<button onclick="controlTask('${item.id}', 'cancel')" style="background-color: #ff4444;">Cancel</button>`; controls += `<button onclick="controlTask('${item.id}', 'cancel')" style="background-color: #ff4444;">Cancel</button>`;
} else {
historyCount++;
} }
div.innerHTML = ` div.innerHTML = `
@@ -203,8 +225,16 @@
</div> </div>
</div> </div>
`; `;
list.appendChild(div);
if (!isHistory) {
queueList.appendChild(div);
} else {
historyList.appendChild(div);
}
}); });
document.getElementById('queue-count').textContent = `(${activeCount})`;
document.getElementById('history-count').textContent = `(${historyCount})`;
} }
async function controlTask(id, action) { async function controlTask(id, action) {