Release v1.5.94

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe 2026-03-04 03:51:10 +01:00
parent bb8fd0646a
commit 4fcbd5c4f7
4 changed files with 21 additions and 7 deletions

View File

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

View File

@ -3728,7 +3728,9 @@ export class DownloadManager extends EventEmitter {
}
delete this.session.packages[packageId];
this.session.packageOrder = this.session.packageOrder.filter((id) => id !== packageId);
this.runPackageIds.delete(packageId);
// Keep packageId in runPackageIds so the "size > 0" guard still filters
// other packages. The deleted package has no items left, so the scheduler
// simply won't find anything for it. finishRun() clears runPackageIds.
this.runCompletedPackages.delete(packageId);
this.hybridExtractRequeue.delete(packageId);
this.resetSessionTotalsIfQueueEmpty();
@ -5716,9 +5718,11 @@ export class DownloadManager extends EventEmitter {
if (!allMissingExistOnDisk) {
continue;
}
// Any non-completed item blocks extraction — cancelled/stopped items may
// have partial files on disk that would corrupt the extraction.
const anyActivelyProcessing = missingParts.some((part) => {
const status = pendingItemStatus.get(pathKey(part));
return status !== undefined && status !== "failed" && status !== "cancelled";
return status !== undefined && status !== "failed";
});
if (anyActivelyProcessing) {
continue;
@ -6008,6 +6012,11 @@ export class DownloadManager extends EventEmitter {
pkg.updatedAt = nowMs();
return;
}
// Immediately clean up extracted items if "Sofort" policy is active
this.applyPackageDoneCleanup(packageId);
if (!this.session.packages[packageId]) {
return; // Package was fully cleaned up
}
pkg.status = (pkg.enabled && !this.session.paused) ? "downloading" : "paused";
pkg.updatedAt = nowMs();
this.emitState();

View File

@ -18,6 +18,7 @@ const VALID_DOWNLOAD_STATUSES = new Set<DownloadStatus>([
"queued", "validating", "downloading", "paused", "reconnect_wait", "extracting", "integrity_check", "completed", "failed", "cancelled"
]);
const VALID_ITEM_PROVIDERS = new Set<DebridProvider>(["realdebrid", "megadebrid", "bestdebrid", "alldebrid"]);
const VALID_ONLINE_STATUSES = new Set(["online", "offline", "checking"]);
function asText(value: unknown): string {
return String(value ?? "").trim();
@ -258,7 +259,6 @@ function normalizeLoadedSession(raw: unknown): SessionState {
const providerRaw = asText(item.provider) as DebridProvider;
const onlineStatusRaw = asText(item.onlineStatus);
const validOnlineStatuses = new Set(["online", "offline", "checking"]);
itemsById[id] = {
id,
@ -277,7 +277,7 @@ function normalizeLoadedSession(raw: unknown): SessionState {
attempts: clampNumber(item.attempts, 0, 0, 10_000),
lastError: asText(item.lastError),
fullStatus: asText(item.fullStatus),
onlineStatus: validOnlineStatuses.has(onlineStatusRaw) ? onlineStatusRaw as "online" | "offline" | "checking" : undefined,
onlineStatus: VALID_ONLINE_STATUSES.has(onlineStatusRaw) ? onlineStatusRaw as "online" | "offline" | "checking" : undefined,
createdAt: clampNumber(item.createdAt, now, 0, Number.MAX_SAFE_INTEGER),
updatedAt: clampNumber(item.updatedAt, now, 0, Number.MAX_SAFE_INTEGER)
};

View File

@ -3078,6 +3078,11 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
const extracted = items.filter((item) => item.fullStatus?.startsWith("Entpackt")).length;
const extracting = items.some((item) => item.fullStatus?.startsWith("Entpack"));
const total = Math.max(1, items.length);
// Use 50/50 split when extraction is active OR package is in extracting state
// (prevents bar jumping from 100% to 50% when extraction starts)
const allDownloaded = done + failed + cancelled >= total;
const allExtracted = extracted >= total;
const useExtractSplit = extracting || pkg.status === "extracting" || (allDownloaded && !allExtracted && done > 0 && extracted > 0);
// Include fractional progress from active downloads so the bar moves continuously
const activeProgress = items.reduce((sum, item) => {
if (item.status === "downloading" || (item.status === "queued" && (item.progressPercent || 0) > 0)) {
@ -3085,7 +3090,7 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
}
return sum;
}, 0);
const dlProgress = Math.floor(((done + activeProgress) / total) * (extracting ? 50 : 100));
const dlProgress = Math.floor(((done + activeProgress) / total) * (useExtractSplit ? 50 : 100));
// Include fractional progress from items currently being extracted
const extractingProgress = items.reduce((sum, item) => {
const fs = item.fullStatus || "";
@ -3095,7 +3100,7 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
return sum;
}, 0);
const exProgress = Math.floor(((extracted + extractingProgress) / total) * 50);
const combinedProgress = extracting ? dlProgress + exProgress : dlProgress;
const combinedProgress = useExtractSplit ? dlProgress + exProgress : dlProgress;
const onKeyDown = (e: KeyboardEvent<HTMLInputElement>): void => {
if (e.key === "Enter") { onFinishEdit(pkg.id, pkg.name, editingName); }