Release v1.5.78

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe 2026-03-03 23:17:37 +01:00
parent 956cad0da4
commit c4aefb6175
4 changed files with 21 additions and 26 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "real-debrid-downloader", "name": "real-debrid-downloader",
"version": "1.5.77", "version": "1.5.78",
"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",

View File

@ -5216,7 +5216,7 @@ export class DownloadManager extends EventEmitter {
let allMissingExistOnDisk = true; let allMissingExistOnDisk = true;
for (const part of missingParts) { for (const part of missingParts) {
try { try {
const stat = fs.statSync(part); const stat = await fs.promises.stat(part);
if (stat.size < 10240) { if (stat.size < 10240) {
allMissingExistOnDisk = false; allMissingExistOnDisk = false;
break; break;
@ -5466,7 +5466,7 @@ export class DownloadManager extends EventEmitter {
continue; continue;
} }
try { try {
const stat = fs.statSync(item.targetPath); const stat = await fs.promises.stat(item.targetPath);
// Require file to be either ≥50% of expected size or at least 10 KB to avoid // Require file to be either ≥50% of expected size or at least 10 KB to avoid
// recovering tiny error-response files (e.g. 9-byte "Forbidden" pages). // recovering tiny error-response files (e.g. 9-byte "Forbidden" pages).
const minSize = item.totalBytes && item.totalBytes > 0 const minSize = item.totalBytes && item.totalBytes > 0

View File

@ -69,9 +69,10 @@ const emptySnapshot = (): UiSnapshot => ({
cleanupMode: "none", extractConflictMode: "overwrite", removeLinkFilesAfterExtract: false, cleanupMode: "none", extractConflictMode: "overwrite", removeLinkFilesAfterExtract: false,
removeSamplesAfterExtract: false, enableIntegrityCheck: true, autoResumeOnStart: true, removeSamplesAfterExtract: false, enableIntegrityCheck: true, autoResumeOnStart: true,
autoReconnect: false, reconnectWaitSeconds: 45, completedCleanupPolicy: "never", autoReconnect: false, reconnectWaitSeconds: 45, completedCleanupPolicy: "never",
maxParallel: 4, retryLimit: 0, speedLimitEnabled: false, speedLimitKbps: 0, speedLimitMode: "global", maxParallel: 4, maxParallelExtract: 2, retryLimit: 0, speedLimitEnabled: false, speedLimitKbps: 0, speedLimitMode: "global",
updateRepo: "", autoUpdateCheck: true, clipboardWatch: false, minimizeToTray: false, updateRepo: "", autoUpdateCheck: true, clipboardWatch: false, minimizeToTray: false,
theme: "dark", collapseNewPackages: true, bandwidthSchedules: [] theme: "dark", collapseNewPackages: true, autoSkipExtracted: false, confirmDeleteSelection: true,
bandwidthSchedules: [], totalDownloadedAllTime: 0
}, },
session: { session: {
version: 2, packageOrder: [], packages: {}, items: {}, runStartedAt: 0, version: 2, packageOrder: [], packages: {}, items: {}, runStartedAt: 0,
@ -144,7 +145,7 @@ const BandwidthChart = memo(function BandwidthChart({ items, running, paused, sp
const canvasRef = useRef<HTMLCanvasElement>(null); const canvasRef = useRef<HTMLCanvasElement>(null);
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const lastUpdateRef = useRef<number>(0); const lastUpdateRef = useRef<number>(0);
const [, forceUpdate] = useState(0);
const animationFrameRef = useRef<number>(0); const animationFrameRef = useRef<number>(0);
const drawChart = useCallback(() => { const drawChart = useCallback(() => {
@ -268,13 +269,10 @@ const BandwidthChart = memo(function BandwidthChart({ items, running, paused, sp
useEffect(() => { useEffect(() => {
const interval = setInterval(() => { const interval = setInterval(() => {
const now = Date.now(); drawChart();
if (now - lastUpdateRef.current >= 250) {
forceUpdate((n) => n + 1);
}
}, 250); }, 250);
return () => clearInterval(interval); return () => clearInterval(interval);
}, []); }, [drawChart]);
useEffect(() => { useEffect(() => {
const now = Date.now(); const now = Date.now();
@ -313,7 +311,7 @@ const BandwidthChart = memo(function BandwidthChart({ items, running, paused, sp
useEffect(() => { useEffect(() => {
drawChart(); drawChart();
}); }, [drawChart, items, paused]);
return ( return (
<div ref={containerRef} className="bandwidth-chart-container"> <div ref={containerRef} className="bandwidth-chart-container">
@ -466,6 +464,8 @@ export function App(): ReactElement {
const settingsDirtyRef = useRef(false); const settingsDirtyRef = useRef(false);
const settingsDraftRevisionRef = useRef(0); const settingsDraftRevisionRef = useRef(0);
const latestStateRef = useRef<UiSnapshot | null>(null); const latestStateRef = useRef<UiSnapshot | null>(null);
const snapshotRef = useRef(snapshot);
snapshotRef.current = snapshot;
const stateFlushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null); const stateFlushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const toastTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null); const toastTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const [dragOver, setDragOver] = useState(false); const [dragOver, setDragOver] = useState(false);
@ -1649,13 +1649,11 @@ export function App(): ReactElement {
}, [contextMenu]); }, [contextMenu]);
const executeDeleteSelection = useCallback((ids: Set<string>): void => { const executeDeleteSelection = useCallback((ids: Set<string>): void => {
setSnapshot((prev) => { const current = snapshotRef.current;
for (const id of ids) { for (const id of ids) {
if (prev.session.items[id]) void window.rd.removeItem(id); if (current.session.items[id]) void window.rd.removeItem(id);
else if (prev.session.packages[id]) void window.rd.cancelPackage(id); else if (current.session.packages[id]) void window.rd.cancelPackage(id);
} }
return prev;
});
setSelectedIds(new Set()); setSelectedIds(new Set());
}, []); }, []);
@ -1752,10 +1750,7 @@ export function App(): ReactElement {
if (!e.shiftKey && e.key.toLowerCase() === "o") { if (!e.shiftKey && e.key.toLowerCase() === "o") {
e.preventDefault(); e.preventDefault();
setOpenMenu(null); setOpenMenu(null);
void window.rd.pickContainers().then(async (files) => { void onImportDlc();
if (files.length === 0) { return; }
await window.rd.addContainers(files);
}).catch(() => undefined);
return; return;
} }
} }

View File

@ -577,7 +577,7 @@ body,
.pkg-column-header { .pkg-column-header {
display: grid; display: grid;
grid-template-columns: 1fr 90px 170px 140px 130px 180px 100px; grid-template-columns: 1fr 170px 90px 140px 130px 180px 100px;
gap: 8px; gap: 8px;
padding: 5px 12px; padding: 5px 12px;
background: var(--card); background: var(--card);
@ -612,7 +612,7 @@ body,
.pkg-columns { .pkg-columns {
display: grid; display: grid;
grid-template-columns: 1fr 90px 170px 140px 130px 180px 100px; grid-template-columns: 1fr 170px 90px 140px 130px 180px 100px;
gap: 8px; gap: 8px;
align-items: center; align-items: center;
min-width: 0; min-width: 0;
@ -1284,7 +1284,7 @@ td {
.item-row { .item-row {
display: grid; display: grid;
grid-template-columns: 1fr 90px 170px 140px 130px 180px 100px; grid-template-columns: 1fr 170px 90px 140px 130px 180px 100px;
gap: 8px; gap: 8px;
align-items: center; align-items: center;
margin: 0 -12px; margin: 0 -12px;