Release v1.6.89

This commit is contained in:
Sucukdeluxe 2026-03-06 20:19:17 +01:00
parent 272b43d59e
commit 0eb3403e40
5 changed files with 54 additions and 25 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "real-debrid-downloader",
"version": "1.6.88",
"version": "1.6.89",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "real-debrid-downloader",
"version": "1.6.88",
"version": "1.6.89",
"license": "MIT",
"dependencies": {
"adm-zip": "^0.5.16",

View File

@ -1,6 +1,6 @@
{
"name": "real-debrid-downloader",
"version": "1.6.88",
"version": "1.6.89",
"description": "Desktop downloader",
"main": "build/main/main/main.js",
"author": "Sucukdeluxe",

View File

@ -4454,28 +4454,23 @@ export class DownloadManager extends EventEmitter {
return provider;
}
private reservePacedStartForItem(item: DownloadItem, now: number): boolean {
private delayPacedStartForItem(item: DownloadItem, now: number): boolean {
const paceKey = this.getPacedStartKeyForItem(item);
if (!paceKey) {
return false;
}
const activeCount = this.getProviderActiveTaskCount("alldebrid");
if (activeCount <= 0 && !this.providerStartReservations.has(paceKey)) {
return false;
}
const baseDelayMs = activeCount * ALLDEBRID_START_STAGGER_MS;
const reservedAt = this.providerStartReservations.get(paceKey) || 0;
const earliestAt = Math.max(now + baseDelayMs, reservedAt);
if (earliestAt <= now) {
const nextAllowedAt = this.providerStartReservations.get(paceKey) || 0;
if (nextAllowedAt <= now) {
return false;
}
const existingReadyAt = this.retryAfterByItem.get(item.id) || 0;
const scheduledAt = Math.max(existingReadyAt, earliestAt);
const scheduledAt = Math.max(existingReadyAt, nextAllowedAt);
if (scheduledAt <= now) {
return false;
}
this.retryAfterByItem.set(item.id, scheduledAt);
this.providerStartReservations.set(paceKey, scheduledAt + ALLDEBRID_START_STAGGER_MS);
item.status = "queued";
item.speedBps = 0;
item.fullStatus = `AllDebrid Start in ${Math.max(1, Math.ceil((scheduledAt - now) / 1000))}s`;
@ -4483,6 +4478,21 @@ export class DownloadManager extends EventEmitter {
return true;
}
private notePacedStartForItem(item: DownloadItem, now: number): void {
const paceKey = this.getPacedStartKeyForItem(item);
if (!paceKey) {
return;
}
const activeCount = this.getProviderActiveTaskCount("alldebrid");
if (activeCount <= 0) {
this.providerStartReservations.delete(paceKey);
return;
}
this.providerStartReservations.set(paceKey, now + activeCount * ALLDEBRID_START_STAGGER_MS);
}
private getAllDebridStartLimit(hosterKey: string): number {
if (hosterKey !== "rapidgator") {
return Number.MAX_SAFE_INTEGER;
@ -4863,7 +4873,7 @@ export class DownloadManager extends EventEmitter {
this.retryAfterByItem.delete(itemId);
}
if (item.status === "queued" || item.status === "reconnect_wait") {
if (this.reservePacedStartForItem(item, now)) {
if (this.delayPacedStartForItem(item, now)) {
continue;
}
if (this.shouldDelayStartForItem(item)) {
@ -5014,6 +5024,7 @@ export class DownloadManager extends EventEmitter {
blockedOnDiskSince: 0
};
this.activeTasks.set(itemId, active);
this.notePacedStartForItem(item, nowMs());
this.emitState();
void this.processItem(active).catch((err) => {

View File

@ -1914,6 +1914,29 @@ export function App(): ReactElement {
});
};
const onToggleAccountEnabled = async (entry: ConfiguredAccountEntry): Promise<void> => {
await performQuickAction(async () => {
const provider = entry.service as DebridProvider;
const current = settingsDraft.disabledProviders || [];
const nextDisabledProviders = current.includes(provider)
? current.filter((existing) => existing !== provider)
: [...current, provider];
const nextDraft: AppSettings = {
...settingsDraft,
disabledProviders: nextDisabledProviders
};
await persistSpecificSettings(nextDraft);
showToast(
nextDisabledProviders.includes(provider)
? `${entry.serviceLabel} deaktiviert`
: `${entry.serviceLabel} aktiviert`,
2200
);
}, (error) => {
showToast(`${entry.serviceLabel} konnte nicht umgeschaltet werden: ${String(error)}`, 3200);
});
};
const onCheckUpdates = async (): Promise<void> => {
let updateResult: UpdateCheckResult | null = null;
await performQuickAction(async () => {
@ -3687,12 +3710,7 @@ export function App(): ReactElement {
{quickAction.label}
</button>
)}
<button className="btn" disabled={actionBusy} onClick={() => {
const provider = entry.service as DebridProvider;
const current = settingsDraft.disabledProviders || [];
const next = current.includes(provider) ? current.filter((p) => p !== provider) : [...current, provider];
setSettingsDraft((prev) => ({ ...prev, disabledProviders: next }));
}}>
<button className="btn" disabled={actionBusy} onClick={() => { void onToggleAccountEnabled(entry); }}>
{entry.disabled ? "Aktivieren" : "Deaktivieren"}
</button>
<button className="btn" disabled={actionBusy} onClick={() => openEditAccountDialog(entry.kind)}>

View File

@ -3161,9 +3161,9 @@ describe("download manager", () => {
const secondDelay = readyTimes[1] - now;
expect(firstDelay).toBeGreaterThan(1500);
expect(firstDelay).toBeLessThan(4500);
expect(secondDelay).toBeGreaterThan(3500);
expect(secondDelay).toBeLessThan(7000);
expect(secondDelay - firstDelay).toBeGreaterThan(1500);
expect(secondDelay).toBeGreaterThan(1500);
expect(secondDelay).toBeLessThan(4500);
expect(Math.abs(secondDelay - firstDelay)).toBeLessThan(1000);
manager.stop();
await waitFor(() => !manager.getSnapshot().session.running, 15000);