From 499179fd40c2bea7a1f46176c20cefef25465179 Mon Sep 17 00:00:00 2001 From: Honey Date: Sun, 26 Apr 2026 14:06:45 +0200 Subject: [PATCH] Show toast when download is skipped due to duplicate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend: set skipped:true on job when track already exists on disk. Album downloads report "X geladen, Y bereits vorhanden" in the message. Frontend: pollJob shows "⏭ bereits auf dem Server" instead of "✅ gespeichert" when the job has skipped:true. Co-Authored-By: Claude Sonnet 4.6 --- backend/novasonic-server.js | 28 ++++++++++++++++++++-------- src/ui.js | 5 ++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/backend/novasonic-server.js b/backend/novasonic-server.js index dac9870..d8e1550 100644 --- a/backend/novasonic-server.js +++ b/backend/novasonic-server.js @@ -245,11 +245,11 @@ async function downloadTrack({ jobId, artist, albumArtist, title, album, year, t async function downloadAlbumTracks({ jobId, artist, albumTitle, tracks, artworkUrl }) { const total = tracks.length; log(jobId, `📀 Album "${albumTitle}" — ${total} Tracks`); - let done = 0; + let done = 0, skipped = 0; for (const track of tracks) { try { - await downloadTrack({ + const result = await downloadTrack({ jobId, artist: track.artistName || artist, // track artist (may include feat.) albumArtist: artist, // always the main artist → consistent grouping @@ -265,12 +265,13 @@ async function downloadAlbumTracks({ jobId, artist, albumTitle, tracks, artworkU artworkUrl: artworkUrl || track.artworkUrl100, outputDir: CONFIG.musicPath, }); - done++; - updateJob(jobId, { progress: Math.round((done / total) * 90) }); + if (result?.skipped) skipped++; else done++; + updateJob(jobId, { progress: Math.round(((done + skipped) / total) * 90) }); } catch (e) { log(jobId, `⚠️ Fehler bei "${track.trackName || track.title}": ${e.message}`); } } + return { done, skipped }; } // Search iTunes for album tracks by artist + album name (fallback when no collectionId) @@ -350,8 +351,12 @@ app.post('/api/download', async (req, res) => { updateJob(jobId, { status: 'running', progress: 5, message: 'Gestartet…' }); try { if (type === 'track') { - await downloadTrack({ jobId, artist, title, album, artworkUrl }); - updateJob(jobId, { status: 'done', progress: 100, message: 'Fertig!' }); + const result = await downloadTrack({ jobId, artist, title, album, artworkUrl }); + if (result?.skipped) { + updateJob(jobId, { status: 'done', progress: 100, message: 'Bereits vorhanden – übersprungen', skipped: true }); + } else { + updateJob(jobId, { status: 'done', progress: 100, message: 'Fertig!' }); + } } else if (type === 'album') { let tracks = []; @@ -366,8 +371,15 @@ app.post('/api/download', async (req, res) => { if (!tracks.length) { throw new Error(`Keine einzelnen Tracks für "${album || title}" gefunden. Bitte über iTunes Global-Suche herunterladen.`); } - await downloadAlbumTracks({ jobId, artist, albumTitle: album || title, tracks, artworkUrl }); - updateJob(jobId, { status: 'done', progress: 100, message: `Album "${album || title}" fertig!` }); + const { done: dlDone, skipped: dlSkipped } = await downloadAlbumTracks({ jobId, artist, albumTitle: album || title, tracks, artworkUrl }); + const allSkipped = dlSkipped === tracks.length; + const someSkipped = dlSkipped > 0 && !allSkipped; + const msg = allSkipped + ? `Album bereits vorhanden – alle ${dlSkipped} Tracks übersprungen` + : someSkipped + ? `Album fertig! (${dlDone} geladen, ${dlSkipped} bereits vorhanden)` + : `Album "${album || title}" fertig!`; + updateJob(jobId, { status: 'done', progress: 100, message: msg, skipped: allSkipped }); } else if (type === 'artist') { log(jobId, `🎤 Künstler-Download: ${artist}`); diff --git a/src/ui.js b/src/ui.js index e5308de..8e96f87 100644 --- a/src/ui.js +++ b/src/ui.js @@ -312,7 +312,10 @@ async function pollJob(jobId) { const d = await res.json(); updateJob(jobId, d.status, d.message, d.progress); if(d.status!=='done' && d.status!=='error') setTimeout(() => pollJob(jobId), 1500); - else if(d.status==='done') toast(`✅ ${S.jobs[jobId]?.title||'Track'} gespeichert!`); + else if(d.status==='done') { + const title = S.jobs[jobId]?.title || 'Track'; + toast(d.skipped ? `⏭ "${title}" bereits auf dem Server` : `✅ ${title} gespeichert!`); + } } catch { updateJob(jobId, 'error', 'Status-Abfrage fehlgeschlagen'); } }