Release v1.6.21
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
729aa30253
commit
1ed13f7f88
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "real-debrid-downloader",
|
"name": "real-debrid-downloader",
|
||||||
"version": "1.6.20",
|
"version": "1.6.21",
|
||||||
"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",
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import { parseCollectorInput } from "./link-parser";
|
|||||||
import { configureLogger, getLogFilePath, logger } from "./logger";
|
import { configureLogger, getLogFilePath, logger } from "./logger";
|
||||||
import { initSessionLog, getSessionLogPath, shutdownSessionLog } from "./session-log";
|
import { initSessionLog, getSessionLogPath, shutdownSessionLog } from "./session-log";
|
||||||
import { MegaWebFallback } from "./mega-web-fallback";
|
import { MegaWebFallback } from "./mega-web-fallback";
|
||||||
import { addHistoryEntry, clearHistory, createStoragePaths, loadHistory, loadSession, loadSettings, normalizeSettings, removeHistoryEntry, saveSession, saveSettings } from "./storage";
|
import { addHistoryEntry, clearHistory, createStoragePaths, loadHistory, loadSession, loadSettings, normalizeLoadedSession, normalizeLoadedSessionTransientFields, normalizeSettings, removeHistoryEntry, saveSession, saveSettings } from "./storage";
|
||||||
import { abortActiveUpdateDownload, checkGitHubUpdate, installLatestUpdate } from "./update";
|
import { abortActiveUpdateDownload, checkGitHubUpdate, installLatestUpdate } from "./update";
|
||||||
import { startDebugServer, stopDebugServer } from "./debug-server";
|
import { startDebugServer, stopDebugServer } from "./debug-server";
|
||||||
|
|
||||||
@ -309,7 +309,9 @@ export class AppController {
|
|||||||
// Cancel any deferred persist timer so the old in-memory session
|
// Cancel any deferred persist timer so the old in-memory session
|
||||||
// does not overwrite the restored session file on disk.
|
// does not overwrite the restored session file on disk.
|
||||||
this.manager.clearPersistTimer();
|
this.manager.clearPersistTimer();
|
||||||
const restoredSession = parsed.session as ReturnType<typeof loadSession>;
|
const restoredSession = normalizeLoadedSessionTransientFields(
|
||||||
|
normalizeLoadedSession(parsed.session)
|
||||||
|
);
|
||||||
saveSession(this.storagePaths, restoredSession);
|
saveSession(this.storagePaths, restoredSession);
|
||||||
return { restored: true, message: "Backup wiederhergestellt. Bitte App neustarten." };
|
return { restored: true, message: "Backup wiederhergestellt. Bitte App neustarten." };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2540,6 +2540,14 @@ export class DownloadManager extends EventEmitter {
|
|||||||
pkg.updatedAt = nowMs();
|
pkg.updatedAt = nowMs();
|
||||||
this.historyRecordedPackages.delete(packageId);
|
this.historyRecordedPackages.delete(packageId);
|
||||||
|
|
||||||
|
// 5. Re-add to runItemIds/runPackageIds if session is running so outcomes are tracked
|
||||||
|
if (this.session.running) {
|
||||||
|
for (const itemId of itemIds) {
|
||||||
|
this.runItemIds.add(itemId);
|
||||||
|
}
|
||||||
|
this.runPackageIds.add(packageId);
|
||||||
|
}
|
||||||
|
|
||||||
logger.info(`Paket "${pkg.name}" zurückgesetzt (${itemIds.length} Items)`);
|
logger.info(`Paket "${pkg.name}" zurückgesetzt (${itemIds.length} Items)`);
|
||||||
this.persistSoon();
|
this.persistSoon();
|
||||||
this.emitState(true);
|
this.emitState(true);
|
||||||
|
|||||||
@ -1993,6 +1993,7 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
const sig = await detectArchiveSignature(archivePath);
|
const sig = await detectArchiveSignature(archivePath);
|
||||||
if (!sig) {
|
if (!sig) {
|
||||||
logger.info(`Generische Split-Datei übersprungen (keine Archiv-Signatur): ${archiveName}`);
|
logger.info(`Generische Split-Datei übersprungen (keine Archiv-Signatur): ${archiveName}`);
|
||||||
|
extracted += 1;
|
||||||
clearInterval(pulseTimer);
|
clearInterval(pulseTimer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2200,10 +2201,8 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
resumeCompleted.add(nestedKey);
|
resumeCompleted.add(nestedKey);
|
||||||
await writeExtractResumeState(options.packageDir, resumeCompleted, options.packageId);
|
await writeExtractResumeState(options.packageDir, resumeCompleted, options.packageId);
|
||||||
logger.info(`Nested-Entpacken erfolgreich: ${nestedName}`);
|
logger.info(`Nested-Entpacken erfolgreich: ${nestedName}`);
|
||||||
if (options.cleanupMode === "delete") {
|
if (options.cleanupMode !== "none") {
|
||||||
for (const part of collectArchiveCleanupTargets(nestedArchive)) {
|
await cleanupArchives([nestedArchive], options.cleanupMode);
|
||||||
try { await fs.promises.unlink(part); } catch { /* ignore */ }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (nestedErr) {
|
} catch (nestedErr) {
|
||||||
const errText = String(nestedErr);
|
const errText = String(nestedErr);
|
||||||
|
|||||||
@ -188,8 +188,7 @@ function sanitizeCredentialPersistence(settings: AppSettings): AppSettings {
|
|||||||
megaLogin: "",
|
megaLogin: "",
|
||||||
megaPassword: "",
|
megaPassword: "",
|
||||||
bestToken: "",
|
bestToken: "",
|
||||||
allDebridToken: "",
|
allDebridToken: ""
|
||||||
archivePasswordList: ""
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +232,7 @@ function readSettingsFile(filePath: string): AppSettings | null {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeLoadedSession(raw: unknown): SessionState {
|
export function normalizeLoadedSession(raw: unknown): SessionState {
|
||||||
const fallback = emptySession();
|
const fallback = emptySession();
|
||||||
const parsed = asRecord(raw);
|
const parsed = asRecord(raw);
|
||||||
if (!parsed) {
|
if (!parsed) {
|
||||||
@ -412,7 +411,7 @@ function sessionBackupPath(sessionFile: string): string {
|
|||||||
return `${sessionFile}.bak`;
|
return `${sessionFile}.bak`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeLoadedSessionTransientFields(session: SessionState): SessionState {
|
export function normalizeLoadedSessionTransientFields(session: SessionState): SessionState {
|
||||||
// Reset transient fields that may be stale from a previous crash
|
// Reset transient fields that may be stale from a previous crash
|
||||||
const ACTIVE_STATUSES = new Set(["downloading", "validating", "extracting", "integrity_check", "paused", "reconnect_wait"]);
|
const ACTIVE_STATUSES = new Set(["downloading", "validating", "extracting", "integrity_check", "paused", "reconnect_wait"]);
|
||||||
for (const item of Object.values(session.items)) {
|
for (const item of Object.values(session.items)) {
|
||||||
|
|||||||
@ -1813,9 +1813,12 @@ export function App(): ReactElement {
|
|||||||
const onKey = (e: KeyboardEvent): void => {
|
const onKey = (e: KeyboardEvent): void => {
|
||||||
if (e.key === "Escape") {
|
if (e.key === "Escape") {
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target as HTMLElement;
|
||||||
if (target.tagName !== "INPUT" && target.tagName !== "TEXTAREA") setSelectedIds(new Set());
|
if (target.tagName !== "INPUT" && target.tagName !== "TEXTAREA") {
|
||||||
|
if (tabRef.current === "downloads") setSelectedIds(new Set());
|
||||||
|
else if (tabRef.current === "history") setSelectedHistoryIds(new Set());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (e.key === "Delete" && selectedIds.size > 0) {
|
if (e.key === "Delete" && tabRef.current === "downloads" && selectedIds.size > 0) {
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target as HTMLElement;
|
||||||
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") return;
|
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -1824,7 +1827,7 @@ export function App(): ReactElement {
|
|||||||
};
|
};
|
||||||
const onDown = (e: MouseEvent): void => {
|
const onDown = (e: MouseEvent): void => {
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target as HTMLElement;
|
||||||
if (target.closest(".package-card") || target.closest(".ctx-menu")) return;
|
if (target.closest(".package-card") || target.closest(".ctx-menu") || target.closest(".modal-backdrop") || target.closest(".modal-card")) return;
|
||||||
setSelectedIds(new Set());
|
setSelectedIds(new Set());
|
||||||
};
|
};
|
||||||
window.addEventListener("keydown", onKey);
|
window.addEventListener("keydown", onKey);
|
||||||
@ -3368,7 +3371,9 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
|
|||||||
if (prev.pkg.updatedAt !== next.pkg.updatedAt
|
if (prev.pkg.updatedAt !== next.pkg.updatedAt
|
||||||
|| prev.pkg.status !== next.pkg.status
|
|| prev.pkg.status !== next.pkg.status
|
||||||
|| prev.pkg.enabled !== next.pkg.enabled
|
|| prev.pkg.enabled !== next.pkg.enabled
|
||||||
|| prev.pkg.name !== next.pkg.name) {
|
|| prev.pkg.name !== next.pkg.name
|
||||||
|
|| prev.pkg.priority !== next.pkg.priority
|
||||||
|
|| prev.pkg.createdAt !== next.pkg.createdAt) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (prev.packageSpeed !== next.packageSpeed
|
if (prev.packageSpeed !== next.packageSpeed
|
||||||
@ -3410,7 +3415,9 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
|
|||||||
|| a.retries !== b.retries
|
|| a.retries !== b.retries
|
||||||
|| a.provider !== b.provider
|
|| a.provider !== b.provider
|
||||||
|| a.fullStatus !== b.fullStatus
|
|| a.fullStatus !== b.fullStatus
|
||||||
|| a.onlineStatus !== b.onlineStatus) {
|
|| a.onlineStatus !== b.onlineStatus
|
||||||
|
|| a.downloadedBytes !== b.downloadedBytes
|
||||||
|
|| a.totalBytes !== b.totalBytes) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user