Round 6 bug fixes (pre-release)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1d0ee31001
commit
0ca359e509
@ -650,7 +650,7 @@ class MegaDebridClient {
|
|||||||
await sleepWithSignal(retryDelay(attempt), signal);
|
await sleepWithSignal(retryDelay(attempt), signal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error(lastError || "Mega-Web Unrestrict fehlgeschlagen");
|
throw new Error(String(lastError || "Mega-Web Unrestrict fehlgeschlagen").replace(/^Error:\s*/i, ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -954,7 +954,7 @@ class AllDebridClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(lastError || "AllDebrid Unrestrict fehlgeschlagen");
|
throw new Error(String(lastError || "AllDebrid Unrestrict fehlgeschlagen").replace(/^Error:\s*/i, ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1102,16 +1102,21 @@ export class DownloadManager extends EventEmitter {
|
|||||||
active.abortController.abort("cancel");
|
active.abortController.abort("cancel");
|
||||||
}
|
}
|
||||||
const pkg = this.session.packages[item.packageId];
|
const pkg = this.session.packages[item.packageId];
|
||||||
|
let removedByPackageCleanup = false;
|
||||||
if (pkg) {
|
if (pkg) {
|
||||||
pkg.itemIds = pkg.itemIds.filter((id) => id !== itemId);
|
pkg.itemIds = pkg.itemIds.filter((id) => id !== itemId);
|
||||||
if (pkg.itemIds.length === 0) {
|
if (pkg.itemIds.length === 0) {
|
||||||
this.removePackageFromSession(item.packageId, [itemId]);
|
this.removePackageFromSession(item.packageId, [itemId]);
|
||||||
|
removedByPackageCleanup = true;
|
||||||
} else {
|
} else {
|
||||||
pkg.updatedAt = nowMs();
|
pkg.updatedAt = nowMs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// removePackageFromSession already deletes the item and decrements itemCount
|
||||||
|
if (!removedByPackageCleanup) {
|
||||||
delete this.session.items[itemId];
|
delete this.session.items[itemId];
|
||||||
this.itemCount = Math.max(0, this.itemCount - 1);
|
this.itemCount = Math.max(0, this.itemCount - 1);
|
||||||
|
}
|
||||||
this.retryAfterByItem.delete(itemId);
|
this.retryAfterByItem.delete(itemId);
|
||||||
this.retryStateByItem.delete(itemId);
|
this.retryStateByItem.delete(itemId);
|
||||||
this.dropItemContribution(itemId);
|
this.dropItemContribution(itemId);
|
||||||
@ -1268,6 +1273,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
this.packagePostProcessTasks.clear();
|
this.packagePostProcessTasks.clear();
|
||||||
this.packagePostProcessAbortControllers.clear();
|
this.packagePostProcessAbortControllers.clear();
|
||||||
this.hybridExtractRequeue.clear();
|
this.hybridExtractRequeue.clear();
|
||||||
|
this.providerFailures.clear();
|
||||||
this.packagePostProcessQueue = Promise.resolve();
|
this.packagePostProcessQueue = Promise.resolve();
|
||||||
this.packagePostProcessActive = 0;
|
this.packagePostProcessActive = 0;
|
||||||
for (const waiter of this.packagePostProcessWaiters) { waiter.resolve(); }
|
for (const waiter of this.packagePostProcessWaiters) { waiter.resolve(); }
|
||||||
@ -1885,7 +1891,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isFile()) {
|
if (entry.isFile() && !isIgnorableEmptyDirFileName(entry.name)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
@ -2739,6 +2745,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
item.updatedAt = nowMs();
|
item.updatedAt = nowMs();
|
||||||
this.retryAfterByItem.delete(itemId);
|
this.retryAfterByItem.delete(itemId);
|
||||||
this.retryStateByItem.delete(itemId);
|
this.retryStateByItem.delete(itemId);
|
||||||
|
this.releaseTargetPath(itemId);
|
||||||
this.recordRunOutcome(itemId, "cancelled");
|
this.recordRunOutcome(itemId, "cancelled");
|
||||||
affectedPackageIds.add(item.packageId);
|
affectedPackageIds.add(item.packageId);
|
||||||
}
|
}
|
||||||
@ -2746,15 +2753,16 @@ export class DownloadManager extends EventEmitter {
|
|||||||
const pkg = this.session.packages[pkgId];
|
const pkg = this.session.packages[pkgId];
|
||||||
if (pkg) this.refreshPackageStatus(pkg);
|
if (pkg) this.refreshPackageStatus(pkg);
|
||||||
}
|
}
|
||||||
// Trigger extraction if all items are now in a terminal state and some completed
|
// Trigger extraction if all items are now in a terminal state and some completed (no failures)
|
||||||
if (this.settings.autoExtract) {
|
if (this.settings.autoExtract) {
|
||||||
for (const pkgId of affectedPackageIds) {
|
for (const pkgId of affectedPackageIds) {
|
||||||
const pkg = this.session.packages[pkgId];
|
const pkg = this.session.packages[pkgId];
|
||||||
if (!pkg || pkg.cancelled || this.packagePostProcessTasks.has(pkgId)) continue;
|
if (!pkg || pkg.cancelled || this.packagePostProcessTasks.has(pkgId)) continue;
|
||||||
const pkgItems = pkg.itemIds.map((id) => this.session.items[id]).filter(Boolean) as DownloadItem[];
|
const pkgItems = pkg.itemIds.map((id) => this.session.items[id]).filter(Boolean) as DownloadItem[];
|
||||||
const hasPending = pkgItems.some((i) => i.status !== "completed" && i.status !== "failed" && i.status !== "cancelled");
|
const hasPending = pkgItems.some((i) => i.status !== "completed" && i.status !== "failed" && i.status !== "cancelled");
|
||||||
|
const hasFailed = pkgItems.some((i) => i.status === "failed");
|
||||||
const hasUnextracted = pkgItems.some((i) => i.status === "completed" && !isExtractedLabel(i.fullStatus || ""));
|
const hasUnextracted = pkgItems.some((i) => i.status === "completed" && !isExtractedLabel(i.fullStatus || ""));
|
||||||
if (!hasPending && hasUnextracted) {
|
if (!hasPending && !hasFailed && hasUnextracted) {
|
||||||
for (const it of pkgItems) {
|
for (const it of pkgItems) {
|
||||||
if (it.status === "completed" && !isExtractedLabel(it.fullStatus || "")) {
|
if (it.status === "completed" && !isExtractedLabel(it.fullStatus || "")) {
|
||||||
it.fullStatus = "Entpacken - Ausstehend";
|
it.fullStatus = "Entpacken - Ausstehend";
|
||||||
@ -2935,6 +2943,9 @@ export class DownloadManager extends EventEmitter {
|
|||||||
this.runCompletedPackages.clear();
|
this.runCompletedPackages.clear();
|
||||||
this.retryAfterByItem.clear();
|
this.retryAfterByItem.clear();
|
||||||
this.retryStateByItem.clear();
|
this.retryStateByItem.clear();
|
||||||
|
this.itemContributedBytes.clear();
|
||||||
|
this.reservedTargetPaths.clear();
|
||||||
|
this.claimedTargetPathByItem.clear();
|
||||||
this.session.running = true;
|
this.session.running = true;
|
||||||
this.session.paused = false;
|
this.session.paused = false;
|
||||||
this.session.runStartedAt = nowMs();
|
this.session.runStartedAt = nowMs();
|
||||||
|
|||||||
@ -1597,7 +1597,8 @@ async function extractZipArchive(archivePath: string, targetDir: string, conflic
|
|||||||
const limitMb = Math.ceil(memoryLimitBytes / (1024 * 1024));
|
const limitMb = Math.ceil(memoryLimitBytes / (1024 * 1024));
|
||||||
throw new Error(`ZIP-Eintrag zu groß für internen Entpacker (${entryMb} MB > ${limitMb} MB)`);
|
throw new Error(`ZIP-Eintrag zu groß für internen Entpacker (${entryMb} MB > ${limitMb} MB)`);
|
||||||
}
|
}
|
||||||
if (data.length > Math.max(uncompressedSize, compressedSize) * 20) {
|
const maxDeclaredSize = Math.max(uncompressedSize, compressedSize);
|
||||||
|
if (maxDeclaredSize > 0 && data.length > maxDeclaredSize * 20) {
|
||||||
throw new Error(`ZIP-Eintrag verdächtig groß nach Entpacken (${entry.entryName})`);
|
throw new Error(`ZIP-Eintrag verdächtig groß nach Entpacken (${entry.entryName})`);
|
||||||
}
|
}
|
||||||
await fs.promises.writeFile(outputPath, data);
|
await fs.promises.writeFile(outputPath, data);
|
||||||
|
|||||||
@ -196,6 +196,6 @@ export class RealDebridClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(lastError || "Unrestrict fehlgeschlagen");
|
throw new Error(String(lastError || "Unrestrict fehlgeschlagen").replace(/^Error:\s*/i, ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1369,10 +1369,18 @@ export function App(): ReactElement {
|
|||||||
pendingPackageOrderRef.current = [...order];
|
pendingPackageOrderRef.current = [...order];
|
||||||
pendingPackageOrderAtRef.current = Date.now();
|
pendingPackageOrderAtRef.current = Date.now();
|
||||||
packageOrderRef.current = [...order];
|
packageOrderRef.current = [...order];
|
||||||
|
setSnapshot((prev) => {
|
||||||
|
if (!prev) return prev;
|
||||||
|
return { ...prev, session: { ...prev.session, packageOrder: [...order] } };
|
||||||
|
});
|
||||||
void window.rd.reorderPackages(order).catch((error) => {
|
void window.rd.reorderPackages(order).catch((error) => {
|
||||||
pendingPackageOrderRef.current = null;
|
pendingPackageOrderRef.current = null;
|
||||||
pendingPackageOrderAtRef.current = 0;
|
pendingPackageOrderAtRef.current = 0;
|
||||||
packageOrderRef.current = serverPackageOrderRef.current;
|
packageOrderRef.current = serverPackageOrderRef.current;
|
||||||
|
setSnapshot((prev) => {
|
||||||
|
if (!prev) return prev;
|
||||||
|
return { ...prev, session: { ...prev.session, packageOrder: serverPackageOrderRef.current } };
|
||||||
|
});
|
||||||
showToast(`Sortierung fehlgeschlagen: ${String(error)}`, 2400);
|
showToast(`Sortierung fehlgeschlagen: ${String(error)}`, 2400);
|
||||||
});
|
});
|
||||||
}, [showToast]);
|
}, [showToast]);
|
||||||
@ -1389,10 +1397,18 @@ export function App(): ReactElement {
|
|||||||
pendingPackageOrderRef.current = [...nextOrder];
|
pendingPackageOrderRef.current = [...nextOrder];
|
||||||
pendingPackageOrderAtRef.current = Date.now();
|
pendingPackageOrderAtRef.current = Date.now();
|
||||||
packageOrderRef.current = [...nextOrder];
|
packageOrderRef.current = [...nextOrder];
|
||||||
|
setSnapshot((prev) => {
|
||||||
|
if (!prev) return prev;
|
||||||
|
return { ...prev, session: { ...prev.session, packageOrder: [...nextOrder] } };
|
||||||
|
});
|
||||||
void window.rd.reorderPackages(nextOrder).catch((error) => {
|
void window.rd.reorderPackages(nextOrder).catch((error) => {
|
||||||
pendingPackageOrderRef.current = null;
|
pendingPackageOrderRef.current = null;
|
||||||
pendingPackageOrderAtRef.current = 0;
|
pendingPackageOrderAtRef.current = 0;
|
||||||
packageOrderRef.current = serverPackageOrderRef.current;
|
packageOrderRef.current = serverPackageOrderRef.current;
|
||||||
|
setSnapshot((prev) => {
|
||||||
|
if (!prev) return prev;
|
||||||
|
return { ...prev, session: { ...prev.session, packageOrder: serverPackageOrderRef.current } };
|
||||||
|
});
|
||||||
showToast(`Sortierung fehlgeschlagen: ${String(error)}`, 2400);
|
showToast(`Sortierung fehlgeschlagen: ${String(error)}`, 2400);
|
||||||
});
|
});
|
||||||
}, [showToast]);
|
}, [showToast]);
|
||||||
@ -2375,10 +2391,18 @@ export function App(): ReactElement {
|
|||||||
pendingPackageOrderRef.current = [...sorted];
|
pendingPackageOrderRef.current = [...sorted];
|
||||||
pendingPackageOrderAtRef.current = Date.now();
|
pendingPackageOrderAtRef.current = Date.now();
|
||||||
packageOrderRef.current = sorted;
|
packageOrderRef.current = sorted;
|
||||||
|
setSnapshot((prev) => {
|
||||||
|
if (!prev) return prev;
|
||||||
|
return { ...prev, session: { ...prev.session, packageOrder: [...sorted] } };
|
||||||
|
});
|
||||||
void window.rd.reorderPackages(sorted).catch((error) => {
|
void window.rd.reorderPackages(sorted).catch((error) => {
|
||||||
pendingPackageOrderRef.current = null;
|
pendingPackageOrderRef.current = null;
|
||||||
pendingPackageOrderAtRef.current = 0;
|
pendingPackageOrderAtRef.current = 0;
|
||||||
packageOrderRef.current = serverPackageOrderRef.current;
|
packageOrderRef.current = serverPackageOrderRef.current;
|
||||||
|
setSnapshot((prev) => {
|
||||||
|
if (!prev) return prev;
|
||||||
|
return { ...prev, session: { ...prev.session, packageOrder: serverPackageOrderRef.current } };
|
||||||
|
});
|
||||||
showToast(`Sortierung fehlgeschlagen: ${String(error)}`, 2400);
|
showToast(`Sortierung fehlgeschlagen: ${String(error)}`, 2400);
|
||||||
});
|
});
|
||||||
} : undefined}
|
} : undefined}
|
||||||
@ -2863,7 +2887,7 @@ export function App(): ReactElement {
|
|||||||
<button className="btn" onClick={() => setDeleteConfirm(null)}>Abbrechen</button>
|
<button className="btn" onClick={() => setDeleteConfirm(null)}>Abbrechen</button>
|
||||||
<button className="btn danger" onClick={() => {
|
<button className="btn danger" onClick={() => {
|
||||||
if (deleteConfirm.dontAsk) {
|
if (deleteConfirm.dontAsk) {
|
||||||
setBool("confirmDeleteSelection", false);
|
setSettingsDraft((prev) => ({ ...prev, confirmDeleteSelection: false }));
|
||||||
void window.rd.updateSettings({ confirmDeleteSelection: false }).catch(() => {});
|
void window.rd.updateSettings({ confirmDeleteSelection: false }).catch(() => {});
|
||||||
}
|
}
|
||||||
executeDeleteSelection(deleteConfirm.ids);
|
executeDeleteSelection(deleteConfirm.ids);
|
||||||
@ -3443,6 +3467,7 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
|
|||||||
}
|
}
|
||||||
if (a.id !== b.id
|
if (a.id !== b.id
|
||||||
|| a.updatedAt !== b.updatedAt
|
|| a.updatedAt !== b.updatedAt
|
||||||
|
|| a.url !== b.url
|
||||||
|| a.status !== b.status
|
|| a.status !== b.status
|
||||||
|| a.fileName !== b.fileName
|
|| a.fileName !== b.fileName
|
||||||
|| a.progressPercent !== b.progressPercent
|
|| a.progressPercent !== b.progressPercent
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user