diff --git a/package.json b/package.json index 368da78..5461bf7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "real-debrid-downloader", - "version": "1.6.21", + "version": "1.6.22", "description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)", "main": "build/main/main/main.js", "author": "Sucukdeluxe", diff --git a/src/main/debrid.ts b/src/main/debrid.ts index 09ff210..cd6fe21 100644 --- a/src/main/debrid.ts +++ b/src/main/debrid.ts @@ -449,7 +449,7 @@ async function resolveRapidgatorFilename(link: string, signal?: AbortSignal): Pr return ""; } catch (error) { const errorText = compactErrorText(error); - if (/aborted/i.test(errorText)) { + if (signal?.aborted || (/aborted/i.test(errorText) && !/timeout/i.test(errorText))) { throw error; } if (attempt >= REQUEST_RETRIES + 2 || !isRetryableErrorText(errorText)) { @@ -530,7 +530,7 @@ export async function checkRapidgatorOnline( break; } catch (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)) { break; // fall through to GET } @@ -583,7 +583,7 @@ export async function checkRapidgatorOnline( return { online: true, fileName, fileSize }; } catch (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)) { return null; } @@ -734,7 +734,7 @@ class BestDebridClient { throw new Error("BestDebrid Antwort ohne Download-Link"); } catch (error) { lastError = compactErrorText(error); - if (signal?.aborted || /aborted/i.test(lastError)) { + if (signal?.aborted || (/aborted/i.test(lastError) && !/timeout/i.test(lastError))) { break; } if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(lastError)) { @@ -828,7 +828,7 @@ class AllDebridClient { break; } catch (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; } if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(errorText)) { @@ -940,7 +940,7 @@ class AllDebridClient { }; } catch (error) { lastError = compactErrorText(error); - if (signal?.aborted || /aborted/i.test(lastError)) { + if (signal?.aborted || (/aborted/i.test(lastError) && !/timeout/i.test(lastError))) { break; } if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(lastError)) { @@ -1002,7 +1002,7 @@ export class DebridService { } } catch (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; } // ignore and continue with host page fallback @@ -1077,7 +1077,7 @@ export class DebridService { }; } catch (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; } attempts.push(`${PROVIDER_LABELS[provider]}: ${compactErrorText(error)}`); diff --git a/src/main/download-manager.ts b/src/main/download-manager.ts index 768dbb7..3edf911 100644 --- a/src/main/download-manager.ts +++ b/src/main/download-manager.ts @@ -1019,6 +1019,7 @@ export class DownloadManager extends EventEmitter { } this.session.totalDownloadedBytes = 0; + this.sessionDownloadedBytes = 0; this.session.runStartedAt = 0; this.lastGlobalProgressBytes = 0; this.lastGlobalProgressAt = nowMs(); @@ -1483,8 +1484,8 @@ export class DownloadManager extends EventEmitter { } const active = this.activeTasks.get(itemId); if (active) { - active.abortReason = "cancel"; - active.abortController.abort("cancel"); + active.abortReason = "reset"; + active.abortController.abort("reset"); } this.releaseTargetPath(itemId); item.status = "queued"; @@ -1623,9 +1624,14 @@ export class DownloadManager extends EventEmitter { continue; } - const result = await checkRapidgatorOnline(url); - checkedUrls.set(url, result); - this.applyRapidgatorCheckResult(item, result); + try { + const result = await checkRapidgatorOnline(url); + checkedUrls.set(url, result); + this.applyRapidgatorCheckResult(item, result); + } catch (err) { + logger.warn(`checkRapidgatorOnline Fehler für ${url}: ${compactErrorText(err)}`); + item.onlineStatus = undefined; + } this.emitState(); } @@ -3468,6 +3474,7 @@ export class DownloadManager extends EventEmitter { const contributed = this.itemContributedBytes.get(itemId) || 0; if (contributed > 0) { this.session.totalDownloadedBytes = Math.max(0, this.session.totalDownloadedBytes - contributed); + this.sessionDownloadedBytes = Math.max(0, this.sessionDownloadedBytes - contributed); } this.itemContributedBytes.delete(itemId); } @@ -6692,9 +6699,12 @@ export class DownloadManager extends EventEmitter { } if (policy === "immediate") { + const item = this.session.items[itemId]; + if (!item || item.status !== "completed") { + return; + } if (this.settings.autoExtract) { - const item = this.session.items[itemId]; - const extracted = item ? isExtractedLabel(item.fullStatus || "") : false; + const extracted = isExtractedLabel(item.fullStatus || ""); if (!extracted) { return; } diff --git a/src/main/realdebrid.ts b/src/main/realdebrid.ts index 082073d..70c86af 100644 --- a/src/main/realdebrid.ts +++ b/src/main/realdebrid.ts @@ -176,7 +176,7 @@ export class RealDebridClient { }; } catch (error) { lastError = compactErrorText(error); - if (signal?.aborted || /aborted/i.test(lastError)) { + if (signal?.aborted || (/aborted/i.test(lastError) && !/timeout/i.test(lastError))) { break; } if (attempt >= REQUEST_RETRIES || !isRetryableErrorText(lastError)) { diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 3885c21..9e654b2 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -1397,17 +1397,18 @@ export function App(): ReactElement { }; const removeCollectorTab = (id: string): void => { + let fallbackId = ""; setCollectorTabs((prev) => { if (prev.length <= 1) return prev; const index = prev.findIndex((tabEntry) => tabEntry.id === id); if (index < 0) return prev; const next = prev.filter((tabEntry) => tabEntry.id !== id); if (activeCollectorTabRef.current === id) { - const fallbackId = next[Math.max(0, index - 1)]?.id ?? next[0]?.id ?? ""; - if (fallbackId) setTimeout(() => setActiveCollectorTab(fallbackId), 0); + fallbackId = next[Math.max(0, index - 1)]?.id ?? next[0]?.id ?? ""; } return next; }); + if (fallbackId) setActiveCollectorTab(fallbackId); }; const onPackageDragStart = useCallback((packageId: string) => { @@ -2362,14 +2363,14 @@ export function App(): ReactElement { )} - {visiblePackages.map((pkg) => ( + {visiblePackages.map((pkg, idx) => (