Release v1.6.27

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe 2026-03-04 20:34:50 +01:00
parent 55b00bf884
commit 9a00304a93
4 changed files with 32 additions and 12 deletions

View File

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

View File

@ -1710,8 +1710,8 @@ export class DownloadManager extends EventEmitter {
item.lastError = "Datei nicht gefunden auf Rapidgator";
item.onlineStatus = "offline";
item.updatedAt = nowMs();
if (this.runItemIds.has(itemId)) {
this.recordRunOutcome(itemId, "failed");
if (this.runItemIds.has(item.id)) {
this.recordRunOutcome(item.id, "failed");
}
// Refresh package status since item was set to failed
const pkg = this.session.packages[item.packageId];
@ -2575,6 +2575,10 @@ export class DownloadManager extends EventEmitter {
if (postProcessController && !postProcessController.signal.aborted) {
postProcessController.abort("reset");
}
this.packagePostProcessAbortControllers.delete(packageId);
this.packagePostProcessTasks.delete(packageId);
this.hybridExtractRequeue.delete(packageId);
this.runCompletedPackages.delete(packageId);
// 3. Clean up extraction progress manifest (.rd_extract_progress.json)
if (pkg.outputDir) {
@ -3418,7 +3422,9 @@ export class DownloadManager extends EventEmitter {
if (this.settings.autoExtract) {
const allExtracted = pkg.itemIds.every((id) => {
const item = this.session.items[id];
return !item || isExtractedLabel(item.fullStatus || "");
if (!item) return true;
if (item.status === "failed" || item.status === "cancelled") return true;
return isExtractedLabel(item.fullStatus || "");
});
if (!allExtracted) continue;
}
@ -4927,6 +4933,7 @@ export class DownloadManager extends EventEmitter {
}
}
this.releaseTargetPath(item.id);
this.dropItemContribution(item.id);
this.queueRetry(item, active, 300, "Netzwerkfehler erkannt, frischer Retry");
item.lastError = "";
item.downloadedBytes = 0;
@ -6373,11 +6380,12 @@ export class DownloadManager extends EventEmitter {
}
const status = entry.fullStatus || "";
if (/^Entpacken\b/i.test(status)) {
if (result.extracted > 0 && result.failed === 0) {
entry.fullStatus = formatExtractDone(nowMs() - hybridExtractStartMs);
} else {
if (result.failed > 0) {
entry.fullStatus = "Entpacken - Error";
} else if (result.extracted > 0) {
entry.fullStatus = formatExtractDone(nowMs() - hybridExtractStartMs);
}
// extracted === 0 && failed === 0: keep current status (no archives to process)
entry.updatedAt = updatedAt;
}
}
@ -6690,7 +6698,9 @@ export class DownloadManager extends EventEmitter {
const timeoutReason = `Entpacken Timeout nach ${Math.ceil(extractTimeoutMs / 1000)}s`;
logger.error(`Post-Processing Entpacken Timeout: pkg=${pkg.name}`);
for (const entry of completedItems) {
entry.fullStatus = `Entpack-Fehler: ${timeoutReason}`;
if (!isExtractedLabel(entry.fullStatus)) {
entry.fullStatus = `Entpack-Fehler: ${timeoutReason}`;
}
entry.updatedAt = nowMs();
}
pkg.status = "failed";
@ -6713,7 +6723,9 @@ export class DownloadManager extends EventEmitter {
const reason = compactErrorText(error);
logger.error(`Post-Processing Entpacken Exception: pkg=${pkg.name}, reason=${reason}`);
for (const entry of completedItems) {
entry.fullStatus = `Entpack-Fehler: ${reason}`;
if (!isExtractedLabel(entry.fullStatus)) {
entry.fullStatus = `Entpack-Fehler: ${reason}`;
}
entry.updatedAt = nowMs();
}
pkg.status = "failed";

View File

@ -424,9 +424,12 @@ async function writeExtractResumeState(packageDir: string, completedArchives: Se
.map((name) => archiveNameKey(name))
.sort((a, b) => a.localeCompare(b))
};
const tmpPath = progressPath + ".tmp";
const tmpPath = progressPath + "." + Date.now() + "." + Math.random().toString(36).slice(2, 8) + ".tmp";
await fs.promises.writeFile(tmpPath, JSON.stringify(payload, null, 2), "utf8");
await fs.promises.rename(tmpPath, progressPath);
await fs.promises.rename(tmpPath, progressPath).catch(async () => {
// rename may fail if another writer renamed tmpPath first (parallel workers)
await fs.promises.rm(tmpPath, { force: true }).catch(() => {});
});
} catch (error) {
logger.warn(`ExtractResumeState schreiben fehlgeschlagen: ${String(error)}`);
}
@ -896,6 +899,8 @@ function resolveJvmExtractorLayout(): JvmExtractorLayout | null {
}) || "";
if (!javaCommand) {
cachedJvmLayout = null;
cachedJvmLayoutNullSince = Date.now();
return null;
}

View File

@ -482,6 +482,7 @@ export function App(): ReactElement {
tabRef.current = tab;
const stateFlushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const toastTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const onImportDlcRef = useRef<() => Promise<void>>(() => Promise.resolve());
const [dragOver, setDragOver] = useState(false);
const [editingPackageId, setEditingPackageId] = useState<string | null>(null);
const [editingName, setEditingName] = useState("");
@ -1199,6 +1200,8 @@ export function App(): ReactElement {
});
};
onImportDlcRef.current = onImportDlc;
const onDrop = async (event: DragEvent<HTMLElement>): Promise<void> => {
event.preventDefault();
dragDepthRef.current = 0;
@ -1929,7 +1932,7 @@ export function App(): ReactElement {
if (inInput) return;
e.preventDefault();
setOpenMenu(null);
void onImportDlc();
void onImportDlcRef.current();
return;
}
if (!e.shiftKey && e.key.toLowerCase() === "a") {