v2.42.2 — HIGH: Background-Service try/finally + MEDIUM: debugPrint Leak
## HIGH: Background-Service bleibt hängen - downloadVonUrl: try/finally stellt sicher dass _stopBackgroundService() immer aufgerufen wird - downloadBatch: try/finally stellt sicher dass _stopBackgroundService() immer aufgerufen wird - reDownload: try/finally stellt sicher dass _stopBackgroundService() immer aufgerufen wird ## MEDIUM: debugPrint Leak - HTTP-Response-Body in debugPrint auf max 200 Zeichen gekürzt
This commit is contained in:
@@ -104,90 +104,95 @@ class DownloadService extends ChangeNotifier {
|
|||||||
/// Song von YouTube herunterladen
|
/// Song von YouTube herunterladen
|
||||||
Future<Song?> downloadVonUrl(String url) async {
|
Future<Song?> downloadVonUrl(String url) async {
|
||||||
_resetStatus();
|
_resetStatus();
|
||||||
final result = await _downloadEinzeln(url);
|
try {
|
||||||
if (!_ladt) _stopBackgroundService();
|
return await _downloadEinzeln(url);
|
||||||
return result;
|
} finally {
|
||||||
|
_stopBackgroundService();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mehrere URLs/Playlists nacheinander mit Cooldown
|
/// Mehrere URLs/Playlists nacheinander mit Cooldown
|
||||||
Future<int> downloadBatch(String input, {int cooldownSekunden = 5}) async {
|
Future<int> downloadBatch(String input, {int cooldownSekunden = 5}) async {
|
||||||
_resetStatus();
|
_resetStatus();
|
||||||
MeloLogger().zustand('download_batch_start', {
|
try {
|
||||||
'input_len': input.length,
|
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)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final song = await _downloadEinzeln(urls[i].url);
|
final urls = _extrahiereUrls(input);
|
||||||
if (song != null) {
|
MeloLogger().zustand('urls_extrahiert', {
|
||||||
erfolgreich++;
|
'anzahl': urls.length,
|
||||||
MeloLogger().zustand('download_einzeln_erfolg', {
|
});
|
||||||
'titel': song.titel,
|
|
||||||
'index': i,
|
if (urls.isEmpty) {
|
||||||
'erfolgreich': erfolgreich,
|
_fehler = 'Keine gültigen URLs gefunden';
|
||||||
});
|
_ladt = false;
|
||||||
} else {
|
notifyListeners();
|
||||||
MeloLogger().zustand('download_einzeln_fehlgeschlagen', {
|
MeloLogger().fehler('keine_urls', 'Input: ${input.substring(0, min(input.length, 80))}');
|
||||||
'index': i,
|
return 0;
|
||||||
'fehler': _fehler ?? 'unbekannt',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cooldown zwischen Downloads (außer beim letzten)
|
int erfolgreich = 0;
|
||||||
if (i < urls.length - 1 && cooldownSekunden > 0) {
|
_aktuellerTitel = '0/${urls.length} – Starte...';
|
||||||
_aktuellerTitel = '✅ $erfolgreich/${urls.length} – Warte ${cooldownSekunden}s...';
|
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();
|
notifyListeners();
|
||||||
for (int s = 0; s < cooldownSekunden; s++) {
|
_showProgress(i, urls.length, titel: urls[i]._titelKurz());
|
||||||
if (sollAbbrechen) break;
|
|
||||||
await Future.delayed(const Duration(seconds: 1));
|
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;
|
_ladt = false;
|
||||||
if (sollAbbrechen) {
|
if (sollAbbrechen) {
|
||||||
_aktuellerTitel = '❌ Abgebrochen ($erfolgreich fertig)';
|
_aktuellerTitel = '❌ Abgebrochen ($erfolgreich fertig)';
|
||||||
} else {
|
} else {
|
||||||
_aktuellerTitel = '✅ $erfolgreich/${urls.length} Songs geladen';
|
_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
|
/// Einzelnen Song über den yt-proxy herunterladen
|
||||||
@@ -256,7 +261,7 @@ class DownloadService extends ChangeNotifier {
|
|||||||
_fehler = 'Proxy-Fehler (${dlAntwort.statusCode}): $fehlerText';
|
_fehler = 'Proxy-Fehler (${dlAntwort.statusCode}): $fehlerText';
|
||||||
_ladt = false;
|
_ladt = false;
|
||||||
notifyListeners();
|
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',
|
MeloLogger().netzwerk('POST', '$_proxyBasisUrl/api/yt-dl',
|
||||||
statusCode: dlAntwort.statusCode, fehler: fehlerText);
|
statusCode: dlAntwort.statusCode, fehler: fehlerText);
|
||||||
return null;
|
return null;
|
||||||
@@ -483,24 +488,28 @@ class DownloadService extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_resetStatus();
|
_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 {
|
try {
|
||||||
final alteDatei = File(song.dateiPfad);
|
_aktuellerTitel = '🔄 Lade neu: ${song.titel}';
|
||||||
if (await alteDatei.exists()) {
|
notifyListeners();
|
||||||
await alteDatei.delete();
|
|
||||||
}
|
|
||||||
} catch (_) {}
|
|
||||||
|
|
||||||
// Neu herunterladen mit der gespeicherten ytUrl
|
// Alten Song-Eintrag aus DB löschen
|
||||||
return _downloadEinzeln(song.ytUrl!);
|
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 ─────────────────
|
// ─── #9: Notification-Progress ─────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user