Fix combined progress display during extraction, fix pause showing Warte auf Daten
Some checks are pending
Build and Release / build (push) Waiting to run
Some checks are pending
Build and Release / build (push) Waiting to run
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c9bace1e5a
commit
19769ea0bb
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "real-debrid-downloader",
|
"name": "real-debrid-downloader",
|
||||||
"version": "1.5.33",
|
"version": "1.5.34",
|
||||||
"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",
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import {
|
|||||||
DownloadSummary,
|
DownloadSummary,
|
||||||
DownloadStatus,
|
DownloadStatus,
|
||||||
DuplicatePolicy,
|
DuplicatePolicy,
|
||||||
|
HistoryEntry,
|
||||||
PackageEntry,
|
PackageEntry,
|
||||||
ParsedPackageInput,
|
ParsedPackageInput,
|
||||||
SessionState,
|
SessionState,
|
||||||
@ -132,11 +133,18 @@ function retryLimitToMaxRetries(retryLimit: number): number {
|
|||||||
return retryLimit <= 0 ? Number.MAX_SAFE_INTEGER : retryLimit;
|
return retryLimit <= 0 ? Number.MAX_SAFE_INTEGER : retryLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HistoryEntryCallback = (entry: HistoryEntry) => void;
|
||||||
|
|
||||||
type DownloadManagerOptions = {
|
type DownloadManagerOptions = {
|
||||||
megaWebUnrestrict?: MegaWebUnrestrictor;
|
megaWebUnrestrict?: MegaWebUnrestrictor;
|
||||||
invalidateMegaSession?: () => void;
|
invalidateMegaSession?: () => void;
|
||||||
|
onHistoryEntry?: HistoryEntryCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function generateHistoryId(): string {
|
||||||
|
return `hist-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
||||||
|
}
|
||||||
|
|
||||||
function cloneSession(session: SessionState): SessionState {
|
function cloneSession(session: SessionState): SessionState {
|
||||||
const clonedItems: Record<string, DownloadItem> = {};
|
const clonedItems: Record<string, DownloadItem> = {};
|
||||||
for (const key of Object.keys(session.items)) {
|
for (const key of Object.keys(session.items)) {
|
||||||
@ -787,6 +795,8 @@ export class DownloadManager extends EventEmitter {
|
|||||||
|
|
||||||
private lastStaleResetAt = 0;
|
private lastStaleResetAt = 0;
|
||||||
|
|
||||||
|
private onHistoryEntryCallback?: HistoryEntryCallback;
|
||||||
|
|
||||||
public constructor(settings: AppSettings, session: SessionState, storagePaths: StoragePaths, options: DownloadManagerOptions = {}) {
|
public constructor(settings: AppSettings, session: SessionState, storagePaths: StoragePaths, options: DownloadManagerOptions = {}) {
|
||||||
super();
|
super();
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
@ -795,6 +805,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
this.storagePaths = storagePaths;
|
this.storagePaths = storagePaths;
|
||||||
this.debridService = new DebridService(settings, { megaWebUnrestrict: options.megaWebUnrestrict });
|
this.debridService = new DebridService(settings, { megaWebUnrestrict: options.megaWebUnrestrict });
|
||||||
this.invalidateMegaSessionFn = options.invalidateMegaSession;
|
this.invalidateMegaSessionFn = options.invalidateMegaSession;
|
||||||
|
this.onHistoryEntryCallback = options.onHistoryEntry;
|
||||||
this.applyOnStartCleanupPolicy();
|
this.applyOnStartCleanupPolicy();
|
||||||
this.normalizeSessionStatuses();
|
this.normalizeSessionStatuses();
|
||||||
void this.recoverRetryableItems("startup").catch((err) => logger.warn(`recoverRetryableItems Fehler (startup): ${compactErrorText(err)}`));
|
void this.recoverRetryableItems("startup").catch((err) => logger.warn(`recoverRetryableItems Fehler (startup): ${compactErrorText(err)}`));
|
||||||
@ -3028,7 +3039,31 @@ export class DownloadManager extends EventEmitter {
|
|||||||
void this.runPackagePostProcessing(packageId).catch((err) => logger.warn(`runPackagePostProcessing Fehler (extractNow): ${compactErrorText(err)}`));
|
void this.runPackagePostProcessing(packageId).catch((err) => logger.warn(`runPackagePostProcessing Fehler (extractNow): ${compactErrorText(err)}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
private removePackageFromSession(packageId: string, itemIds: string[]): void {
|
private removePackageFromSession(packageId: string, itemIds: string[], reason: "completed" | "deleted" = "deleted"): void {
|
||||||
|
const pkg = this.session.packages[packageId];
|
||||||
|
if (pkg && this.onHistoryEntryCallback) {
|
||||||
|
const completedItems = itemIds.map(id => this.session.items[id]).filter(Boolean) as DownloadItem[];
|
||||||
|
const completedCount = completedItems.filter(item => item.status === "completed").length;
|
||||||
|
if (completedCount > 0 && (reason === "completed" || pkg.status === "completed")) {
|
||||||
|
const totalBytes = completedItems.reduce((sum, item) => sum + (item.downloadedBytes || 0), 0);
|
||||||
|
const durationSeconds = pkg.createdAt > 0 ? Math.max(1, Math.floor((nowMs() - pkg.createdAt) / 1000)) : 1;
|
||||||
|
const providers = new Set(completedItems.map(item => item.provider).filter(Boolean));
|
||||||
|
const provider = providers.size === 1 ? [...providers][0] : null;
|
||||||
|
const entry: HistoryEntry = {
|
||||||
|
id: generateHistoryId(),
|
||||||
|
name: pkg.name,
|
||||||
|
totalBytes,
|
||||||
|
downloadedBytes: totalBytes,
|
||||||
|
fileCount: completedCount,
|
||||||
|
provider,
|
||||||
|
completedAt: nowMs(),
|
||||||
|
durationSeconds,
|
||||||
|
status: reason === "completed" ? "completed" : "deleted",
|
||||||
|
outputDir: pkg.outputDir
|
||||||
|
};
|
||||||
|
this.onHistoryEntryCallback(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
const postProcessController = this.packagePostProcessAbortControllers.get(packageId);
|
const postProcessController = this.packagePostProcessAbortControllers.get(packageId);
|
||||||
if (postProcessController && !postProcessController.signal.aborted) {
|
if (postProcessController && !postProcessController.signal.aborted) {
|
||||||
postProcessController.abort("package_removed");
|
postProcessController.abort("package_removed");
|
||||||
@ -4265,7 +4300,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
if (nowTick - lastDataAt < idlePulseMs) {
|
if (nowTick - lastDataAt < idlePulseMs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (item.status === "paused") {
|
if (item.status === "paused" || this.session.paused) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
item.status = "downloading";
|
item.status = "downloading";
|
||||||
@ -5403,7 +5438,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.removePackageFromSession(packageId, [...pkg.itemIds]);
|
this.removePackageFromSession(packageId, [...pkg.itemIds], "completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
private applyCompletedCleanupPolicy(packageId: string, itemId: string): void {
|
private applyCompletedCleanupPolicy(packageId: string, itemId: string): void {
|
||||||
|
|||||||
@ -2773,6 +2773,7 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
|
|||||||
return sum;
|
return sum;
|
||||||
}, 0);
|
}, 0);
|
||||||
const exProgress = Math.floor(((extracted + extractingProgress) / total) * 50);
|
const exProgress = Math.floor(((extracted + extractingProgress) / total) * 50);
|
||||||
|
const combinedProgress = extracting ? dlProgress + exProgress : dlProgress;
|
||||||
|
|
||||||
const onKeyDown = (e: KeyboardEvent<HTMLInputElement>): void => {
|
const onKeyDown = (e: KeyboardEvent<HTMLInputElement>): void => {
|
||||||
if (e.key === "Enter") { onFinishEdit(pkg.id, pkg.name, editingName); }
|
if (e.key === "Enter") { onFinishEdit(pkg.id, pkg.name, editingName); }
|
||||||
@ -2810,9 +2811,9 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
|
|||||||
</div>
|
</div>
|
||||||
<span className="pkg-col pkg-col-progress">
|
<span className="pkg-col pkg-col-progress">
|
||||||
<span className="progress-inline">
|
<span className="progress-inline">
|
||||||
<span className="progress-inline-bar" style={{ width: `${dlProgress}%` }} />
|
<span className="progress-inline-bar" style={{ width: `${combinedProgress}%` }} />
|
||||||
<span className="progress-inline-text">{dlProgress}%</span>
|
<span className="progress-inline-text">{combinedProgress}%</span>
|
||||||
<span className="progress-inline-text-filled" style={{ clipPath: `inset(0 ${100 - dlProgress}% 0 0)` }}>{dlProgress}%</span>
|
<span className="progress-inline-text-filled" style={{ clipPath: `inset(0 ${100 - combinedProgress}% 0 0)` }}>{combinedProgress}%</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="pkg-col pkg-col-size">{(() => {
|
<span className="pkg-col pkg-col-size">{(() => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user