Release v1.6.22

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe 2026-03-04 19:04:53 +01:00
parent 1ed13f7f88
commit 9cceaacd14
5 changed files with 33 additions and 22 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "real-debrid-downloader", "name": "real-debrid-downloader",
"version": "1.6.21", "version": "1.6.22",
"description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)", "description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)",
"main": "build/main/main/main.js", "main": "build/main/main/main.js",
"author": "Sucukdeluxe", "author": "Sucukdeluxe",

View File

@ -449,7 +449,7 @@ async function resolveRapidgatorFilename(link: string, signal?: AbortSignal): Pr
return ""; return "";
} catch (error) { } catch (error) {
const errorText = compactErrorText(error); const errorText = compactErrorText(error);
if (/aborted/i.test(errorText)) { if (signal?.aborted || (/aborted/i.test(errorText) && !/timeout/i.test(errorText))) {
throw error; throw error;
} }
if (attempt >= REQUEST_RETRIES + 2 || !isRetryableErrorText(errorText)) { if (attempt >= REQUEST_RETRIES + 2 || !isRetryableErrorText(errorText)) {
@ -530,7 +530,7 @@ export async function checkRapidgatorOnline(
break; break;
} catch (error) { } catch (error) {
const errorText = compactErrorText(error); const errorText = compactErrorText(error);
if (/aborted/i.test(errorText)) throw error; if (signal?.aborted || (/aborted/i.test(errorText) && !/timeout/i.test(errorText))) throw error;
if (attempt > REQUEST_RETRIES || !isRetryableErrorText(errorText)) { if (attempt > REQUEST_RETRIES || !isRetryableErrorText(errorText)) {
break; // fall through to GET break; // fall through to GET
} }
@ -583,7 +583,7 @@ export async function checkRapidgatorOnline(
return { online: true, fileName, fileSize }; return { online: true, fileName, fileSize };
} catch (error) { } catch (error) {
const errorText = compactErrorText(error); const errorText = compactErrorText(error);
if (/aborted/i.test(errorText)) throw error; if (signal?.aborted || (/aborted/i.test(errorText) && !/timeout/i.test(errorText))) throw error;
if (attempt > REQUEST_RETRIES || !isRetryableErrorText(errorText)) { if (attempt > REQUEST_RETRIES || !isRetryableErrorText(errorText)) {
return null; return null;
} }
@ -734,7 +734,7 @@ class BestDebridClient {
throw new Error("BestDebrid Antwort ohne Download-Link"); throw new Error("BestDebrid Antwort ohne Download-Link");
} catch (error) { } catch (error) {
lastError = compactErrorText(error); lastError = compactErrorText(error);
if (signal?.aborted || /aborted/i.test(lastError)) { if (signal?.aborted || (/aborted/i.test(lastError) && !/timeout/i.test(lastError))) {
break; break;
} }
if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(lastError)) { if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(lastError)) {
@ -828,7 +828,7 @@ class AllDebridClient {
break; break;
} catch (error) { } catch (error) {
const errorText = compactErrorText(error); const errorText = compactErrorText(error);
if (signal?.aborted || /aborted/i.test(errorText)) { if (signal?.aborted || (/aborted/i.test(errorText) && !/timeout/i.test(errorText))) {
throw error; throw error;
} }
if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(errorText)) { if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(errorText)) {
@ -940,7 +940,7 @@ class AllDebridClient {
}; };
} catch (error) { } catch (error) {
lastError = compactErrorText(error); lastError = compactErrorText(error);
if (signal?.aborted || /aborted/i.test(lastError)) { if (signal?.aborted || (/aborted/i.test(lastError) && !/timeout/i.test(lastError))) {
break; break;
} }
if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(lastError)) { if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(lastError)) {
@ -1002,7 +1002,7 @@ export class DebridService {
} }
} catch (error) { } catch (error) {
const errorText = compactErrorText(error); const errorText = compactErrorText(error);
if (signal?.aborted || /aborted/i.test(errorText)) { if (signal?.aborted || (/aborted/i.test(errorText) && !/timeout/i.test(errorText))) {
throw error; throw error;
} }
// ignore and continue with host page fallback // ignore and continue with host page fallback
@ -1077,7 +1077,7 @@ export class DebridService {
}; };
} catch (error) { } catch (error) {
const errorText = compactErrorText(error); const errorText = compactErrorText(error);
if (signal?.aborted || /aborted/i.test(errorText)) { if (signal?.aborted || (/aborted/i.test(errorText) && !/timeout/i.test(errorText))) {
throw error; throw error;
} }
attempts.push(`${PROVIDER_LABELS[provider]}: ${compactErrorText(error)}`); attempts.push(`${PROVIDER_LABELS[provider]}: ${compactErrorText(error)}`);

View File

@ -1019,6 +1019,7 @@ export class DownloadManager extends EventEmitter {
} }
this.session.totalDownloadedBytes = 0; this.session.totalDownloadedBytes = 0;
this.sessionDownloadedBytes = 0;
this.session.runStartedAt = 0; this.session.runStartedAt = 0;
this.lastGlobalProgressBytes = 0; this.lastGlobalProgressBytes = 0;
this.lastGlobalProgressAt = nowMs(); this.lastGlobalProgressAt = nowMs();
@ -1483,8 +1484,8 @@ export class DownloadManager extends EventEmitter {
} }
const active = this.activeTasks.get(itemId); const active = this.activeTasks.get(itemId);
if (active) { if (active) {
active.abortReason = "cancel"; active.abortReason = "reset";
active.abortController.abort("cancel"); active.abortController.abort("reset");
} }
this.releaseTargetPath(itemId); this.releaseTargetPath(itemId);
item.status = "queued"; item.status = "queued";
@ -1623,9 +1624,14 @@ export class DownloadManager extends EventEmitter {
continue; continue;
} }
const result = await checkRapidgatorOnline(url); try {
checkedUrls.set(url, result); const result = await checkRapidgatorOnline(url);
this.applyRapidgatorCheckResult(item, result); checkedUrls.set(url, result);
this.applyRapidgatorCheckResult(item, result);
} catch (err) {
logger.warn(`checkRapidgatorOnline Fehler für ${url}: ${compactErrorText(err)}`);
item.onlineStatus = undefined;
}
this.emitState(); this.emitState();
} }
@ -3468,6 +3474,7 @@ export class DownloadManager extends EventEmitter {
const contributed = this.itemContributedBytes.get(itemId) || 0; const contributed = this.itemContributedBytes.get(itemId) || 0;
if (contributed > 0) { if (contributed > 0) {
this.session.totalDownloadedBytes = Math.max(0, this.session.totalDownloadedBytes - contributed); this.session.totalDownloadedBytes = Math.max(0, this.session.totalDownloadedBytes - contributed);
this.sessionDownloadedBytes = Math.max(0, this.sessionDownloadedBytes - contributed);
} }
this.itemContributedBytes.delete(itemId); this.itemContributedBytes.delete(itemId);
} }
@ -6692,9 +6699,12 @@ export class DownloadManager extends EventEmitter {
} }
if (policy === "immediate") { if (policy === "immediate") {
const item = this.session.items[itemId];
if (!item || item.status !== "completed") {
return;
}
if (this.settings.autoExtract) { if (this.settings.autoExtract) {
const item = this.session.items[itemId]; const extracted = isExtractedLabel(item.fullStatus || "");
const extracted = item ? isExtractedLabel(item.fullStatus || "") : false;
if (!extracted) { if (!extracted) {
return; return;
} }

View File

@ -176,7 +176,7 @@ export class RealDebridClient {
}; };
} catch (error) { } catch (error) {
lastError = compactErrorText(error); lastError = compactErrorText(error);
if (signal?.aborted || /aborted/i.test(lastError)) { if (signal?.aborted || (/aborted/i.test(lastError) && !/timeout/i.test(lastError))) {
break; break;
} }
if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(lastError)) { if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(lastError)) {

View File

@ -1397,17 +1397,18 @@ export function App(): ReactElement {
}; };
const removeCollectorTab = (id: string): void => { const removeCollectorTab = (id: string): void => {
let fallbackId = "";
setCollectorTabs((prev) => { setCollectorTabs((prev) => {
if (prev.length <= 1) return prev; if (prev.length <= 1) return prev;
const index = prev.findIndex((tabEntry) => tabEntry.id === id); const index = prev.findIndex((tabEntry) => tabEntry.id === id);
if (index < 0) return prev; if (index < 0) return prev;
const next = prev.filter((tabEntry) => tabEntry.id !== id); const next = prev.filter((tabEntry) => tabEntry.id !== id);
if (activeCollectorTabRef.current === id) { if (activeCollectorTabRef.current === id) {
const fallbackId = next[Math.max(0, index - 1)]?.id ?? next[0]?.id ?? ""; fallbackId = next[Math.max(0, index - 1)]?.id ?? next[0]?.id ?? "";
if (fallbackId) setTimeout(() => setActiveCollectorTab(fallbackId), 0);
} }
return next; return next;
}); });
if (fallbackId) setActiveCollectorTab(fallbackId);
}; };
const onPackageDragStart = useCallback((packageId: string) => { const onPackageDragStart = useCallback((packageId: string) => {
@ -2362,14 +2363,14 @@ export function App(): ReactElement {
<button className="btn" onClick={() => setShowAllPackages(true)}>Alle trotzdem anzeigen</button> <button className="btn" onClick={() => setShowAllPackages(true)}>Alle trotzdem anzeigen</button>
</div> </div>
)} )}
{visiblePackages.map((pkg) => ( {visiblePackages.map((pkg, idx) => (
<PackageCard <PackageCard
key={pkg.id} key={pkg.id}
pkg={pkg} pkg={pkg}
items={itemsByPackage.get(pkg.id) ?? []} items={itemsByPackage.get(pkg.id) ?? []}
packageSpeed={packageSpeedMap.get(pkg.id) ?? 0} packageSpeed={packageSpeedMap.get(pkg.id) ?? 0}
isFirst={(packagePosition.get(pkg.id) ?? -1) === 0} isFirst={idx === 0}
isLast={(packagePosition.get(pkg.id) ?? -1) === snapshot.session.packageOrder.length - 1} isLast={idx === visiblePackages.length - 1}
isEditing={editingPackageId === pkg.id} isEditing={editingPackageId === pkg.id}
editingName={editingName} editingName={editingName}
collapsed={collapsedPackages[pkg.id] ?? false} collapsed={collapsedPackages[pkg.id] ?? false}