diff --git a/lib/services/download_service.dart b/lib/services/download_service.dart index d6d6d9f..3a54c05 100644 --- a/lib/services/download_service.dart +++ b/lib/services/download_service.dart @@ -104,90 +104,95 @@ class DownloadService extends ChangeNotifier { /// Song von YouTube herunterladen Future downloadVonUrl(String url) async { _resetStatus(); - final result = await _downloadEinzeln(url); - if (!_ladt) _stopBackgroundService(); - return result; + try { + return await _downloadEinzeln(url); + } finally { + _stopBackgroundService(); + } } /// Mehrere URLs/Playlists nacheinander mit Cooldown Future downloadBatch(String input, {int cooldownSekunden = 5}) async { _resetStatus(); - MeloLogger().zustand('download_batch_start', { - 'input_len': input.length, - }); - - final urls = _extrahiereUrls(input); - MeloLogger().zustand('urls_extrahiert', { - 'anzahl': urls.length, - }); - - if (urls.isEmpty) { - _fehler = 'Keine gültigen URLs gefunden'; - _ladt = false; - notifyListeners(); - MeloLogger().fehler('keine_urls', 'Input: ${input.substring(0, min(input.length, 80))}'); - return 0; - } - - int erfolgreich = 0; - _aktuellerTitel = '0/${urls.length} – Starte...'; - notifyListeners(); - _showProgress(0, urls.length); - - for (int i = 0; i < urls.length; i++) { - if (sollAbbrechen) break; - - _aktuellerTitel = '${i + 1}/${urls.length} – ${urls[i]._titelKurz()}'; - notifyListeners(); - _showProgress(i, urls.length, titel: urls[i]._titelKurz()); - - MeloLogger().zustand('download_einzeln_start', { - 'index': i, - 'gesamt': urls.length, - 'url': urls[i].url.substring(0, min(urls[i].url.length, 60)), + try { + MeloLogger().zustand('download_batch_start', { + 'input_len': input.length, }); - final song = await _downloadEinzeln(urls[i].url); - if (song != null) { - erfolgreich++; - MeloLogger().zustand('download_einzeln_erfolg', { - 'titel': song.titel, - 'index': i, - 'erfolgreich': erfolgreich, - }); - } else { - MeloLogger().zustand('download_einzeln_fehlgeschlagen', { - 'index': i, - 'fehler': _fehler ?? 'unbekannt', - }); + final urls = _extrahiereUrls(input); + MeloLogger().zustand('urls_extrahiert', { + 'anzahl': urls.length, + }); + + if (urls.isEmpty) { + _fehler = 'Keine gültigen URLs gefunden'; + _ladt = false; + notifyListeners(); + MeloLogger().fehler('keine_urls', 'Input: ${input.substring(0, min(input.length, 80))}'); + return 0; } - // Cooldown zwischen Downloads (außer beim letzten) - if (i < urls.length - 1 && cooldownSekunden > 0) { - _aktuellerTitel = '✅ $erfolgreich/${urls.length} – Warte ${cooldownSekunden}s...'; + int erfolgreich = 0; + _aktuellerTitel = '0/${urls.length} – Starte...'; + notifyListeners(); + _showProgress(0, urls.length); + + for (int i = 0; i < urls.length; i++) { + if (sollAbbrechen) break; + + _aktuellerTitel = '${i + 1}/${urls.length} – ${urls[i]._titelKurz()}'; notifyListeners(); - for (int s = 0; s < cooldownSekunden; s++) { - if (sollAbbrechen) break; - await Future.delayed(const Duration(seconds: 1)); + _showProgress(i, urls.length, titel: urls[i]._titelKurz()); + + MeloLogger().zustand('download_einzeln_start', { + 'index': i, + 'gesamt': urls.length, + 'url': urls[i].url.substring(0, min(urls[i].url.length, 60)), + }); + + final song = await _downloadEinzeln(urls[i].url); + if (song != null) { + erfolgreich++; + MeloLogger().zustand('download_einzeln_erfolg', { + 'titel': song.titel, + 'index': i, + 'erfolgreich': erfolgreich, + }); + } else { + MeloLogger().zustand('download_einzeln_fehlgeschlagen', { + 'index': i, + 'fehler': _fehler ?? 'unbekannt', + }); + } + + // Cooldown zwischen Downloads (außer beim letzten) + if (i < urls.length - 1 && cooldownSekunden > 0) { + _aktuellerTitel = '✅ $erfolgreich/${urls.length} – Warte ${cooldownSekunden}s...'; + notifyListeners(); + for (int s = 0; s < cooldownSekunden; s++) { + if (sollAbbrechen) break; + await Future.delayed(const Duration(seconds: 1)); + } } } - } - _ladt = false; - if (sollAbbrechen) { - _aktuellerTitel = '❌ Abgebrochen ($erfolgreich fertig)'; - } else { - _aktuellerTitel = '✅ $erfolgreich/${urls.length} Songs geladen'; + _ladt = false; + if (sollAbbrechen) { + _aktuellerTitel = '❌ Abgebrochen ($erfolgreich fertig)'; + } else { + _aktuellerTitel = '✅ $erfolgreich/${urls.length} Songs geladen'; + } + notifyListeners(); + _completeNotification(erfolgreich, urls.length, abgebrochen: sollAbbrechen); + MeloLogger().zustand('download_batch_ende', { + 'erfolgreich': erfolgreich, + 'gesamt': urls.length, + 'abgebrochen': sollAbbrechen, + }); + return erfolgreich; + } finally { + _stopBackgroundService(); } - notifyListeners(); - _completeNotification(erfolgreich, urls.length, abgebrochen: sollAbbrechen); - _stopBackgroundService(); - MeloLogger().zustand('download_batch_ende', { - 'erfolgreich': erfolgreich, - 'gesamt': urls.length, - 'abgebrochen': sollAbbrechen, - }); - return erfolgreich; } /// Einzelnen Song über den yt-proxy herunterladen @@ -256,7 +261,7 @@ class DownloadService extends ChangeNotifier { _fehler = 'Proxy-Fehler (${dlAntwort.statusCode}): $fehlerText'; _ladt = false; notifyListeners(); - debugPrint('Proxy-Fehler: ${dlAntwort.body}'); + debugPrint('Proxy-Fehler: ${dlAntwort.body.length > 200 ? '${dlAntwort.body.substring(0, 200)}...' : dlAntwort.body}'); MeloLogger().netzwerk('POST', '$_proxyBasisUrl/api/yt-dl', statusCode: dlAntwort.statusCode, fehler: fehlerText); return null; @@ -483,24 +488,28 @@ class DownloadService extends ChangeNotifier { } _resetStatus(); - _aktuellerTitel = '🔄 Lade neu: ${song.titel}'; - notifyListeners(); - - // Alten Song-Eintrag aus DB löschen - if (song.id != null) { - await _db.loeschSong(song.id!); - } - - // Alte Datei löschen try { - final alteDatei = File(song.dateiPfad); - if (await alteDatei.exists()) { - await alteDatei.delete(); - } - } catch (_) {} + _aktuellerTitel = '🔄 Lade neu: ${song.titel}'; + notifyListeners(); - // Neu herunterladen mit der gespeicherten ytUrl - return _downloadEinzeln(song.ytUrl!); + // Alten Song-Eintrag aus DB löschen + if (song.id != null) { + await _db.loeschSong(song.id!); + } + + // Alte Datei löschen + try { + final alteDatei = File(song.dateiPfad); + if (await alteDatei.exists()) { + await alteDatei.delete(); + } + } catch (_) {} + + // Neu herunterladen mit der gespeicherten ytUrl + return _downloadEinzeln(song.ytUrl!); + } finally { + _stopBackgroundService(); + } } // ─── #9: Notification-Progress ─────────────────