Compare commits

..

No commits in common. "ce33617aa68b3f69c29bc58ef8699d4f75f9e1bf" and "b92330863ae3c05453e7926e828810cb699aee11" have entirely different histories.

3 changed files with 29 additions and 54 deletions

View File

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

View File

@ -2149,14 +2149,12 @@ export class DownloadManager extends EventEmitter {
}
private resetSessionTotalsIfQueueEmpty(force = false): void {
// Cheap O(1) check via cached counters covers the common case.
// The Object.keys() cross-check below was redundant — itemCount and
// packageOrder are kept in sync with session.items / session.packages
// by every mutation site, so the second check just allocated two
// arrays per call without ever changing the outcome.
if (this.itemCount > 0 || this.session.packageOrder.length > 0) {
return;
}
if (Object.keys(this.session.items).length > 0 || Object.keys(this.session.packages).length > 0) {
return;
}
if (!force && (this.sessionDownloadedBytes > 0 || this.sessionCompletedFiles > 0 || this.itemContributedBytes.size > 0)) {
return;
}
@ -7568,25 +7566,22 @@ export class DownloadManager extends EventEmitter {
let changed = false;
const waitSeconds = Math.max(0, Math.ceil((this.session.reconnectUntil - nowMs()) / 1000));
const waitText = `Reconnect-Wait (${waitSeconds}s)`;
// Iterate without allocating an Object.keys() array (called every 900ms
// during reconnect; with 5000+ items that's a 5000-string allocation per tick).
const updateItem = (itemId: string): void => {
const itemIds = this.runItemIds.size > 0 ? this.runItemIds : Object.keys(this.session.items);
for (const itemId of itemIds) {
const item = this.session.items[itemId];
if (!item) return;
if (!item) {
continue;
}
const pkg = this.session.packages[item.packageId];
if (!pkg || pkg.cancelled || !pkg.enabled) return;
if (!pkg || pkg.cancelled || !pkg.enabled) {
continue;
}
if (item.status === "queued") {
item.status = "reconnect_wait";
item.fullStatus = waitText;
item.updatedAt = nowMs();
changed = true;
}
};
if (this.runItemIds.size > 0) {
for (const itemId of this.runItemIds) updateItem(itemId);
} else {
// for-in iterates own enumerable string keys without allocating an array
for (const itemId in this.session.items) updateItem(itemId);
}
if (changed) {
this.emitState();

View File

@ -1673,22 +1673,15 @@ export function App(): ReactElement {
showToast("Accounts-Spalten zurückgesetzt", 1800);
}, []);
// Sync column order from settings. Avoid JSON.stringify on every render
// (which was a 7-element array stringify per snapshot tick). A simple
// join() is one O(n) string concat without Object/Array allocation overhead,
// and useMemo caches the resulting key so React only sees a new dep when the
// contents actually changed.
const columnOrderKey = useMemo(
() => (snapshot.settings.columnOrder || []).join("|"),
[snapshot.settings.columnOrder]
);
// Sync column order from settings (value-based comparison to avoid reference issues)
const columnOrderJson = JSON.stringify(snapshot.settings.columnOrder);
useEffect(() => {
const order = snapshot.settings.columnOrder;
if (order && order.length > 0) {
setColumnOrder(order);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [columnOrderKey]);
}, [columnOrderJson]);
const currentCollectorTab = collectorTabs.find((t) => t.id === activeCollectorTab) ?? collectorTabs[0];
@ -2064,25 +2057,14 @@ export function App(): ReactElement {
const hiddenPackageCount = shouldLimitPackageRendering
? Math.max(0, totalPackageCount - packages.length)
: 0;
// The sort-by-progress logic only runs when the session is running AND auto-sort
// is enabled AND there's more than one package. When any of those isn't true,
// the items reference is irrelevant — passing null here makes useMemo skip the
// re-evaluation that previously fired on EVERY item update (progress, status,
// speed) even when the sort would have returned the original `packages` array.
const sortRelevantItems = (snapshot.session.running && settingsDraft.autoSortPackagesByProgress && packages.length > 1)
? snapshot.session.items
: null;
const visiblePackages = useMemo(() => {
if (!sortRelevantItems) {
return packages;
}
return sortPackagesForDisplay(
packages,
sortRelevantItems,
true,
true
snapshot.session.items,
snapshot.session.running,
settingsDraft.autoSortPackagesByProgress
);
}, [packages, sortRelevantItems]);
}, [packages, settingsDraft.autoSortPackagesByProgress, snapshot.session.running, snapshot.session.items]);
const hasSavedAllDebridAccount = Boolean(snapshot.settings.allDebridUseWebLogin || snapshot.settings.allDebridToken.trim());
const allDebridSettingsDirty = snapshot.settings.allDebridUseWebLogin !== settingsDraft.allDebridUseWebLogin
@ -6182,12 +6164,6 @@ const ItemRow = memo(function ItemRow({ item, packageId, isSelected, sessionRunn
e.stopPropagation();
onContextMenu(packageId, item.id, e.clientX, e.clientY);
}, [packageId, item.id, onContextMenu]);
// Memoize the date string so it doesn't get re-formatted on every re-render
// when only progress/speed changed but createdAt is stable.
const formattedCreatedAt = useMemo(() => formatDateTime(item.createdAt), [item.createdAt]);
// Memoize the displayed status so we don't compute it twice (title + body)
const displayStatus = useMemo(() => computeDisplayedItemStatus(item, sessionRunning), [item, sessionRunning]);
const statusTitle = displayStatus ? (item.retries > 0 ? `${displayStatus} ? R${item.retries}` : displayStatus) : "";
return (
<div
@ -6237,13 +6213,17 @@ const ItemRow = memo(function ItemRow({ item, packageId, isSelected, sessionRunn
case "hoster": { const h = extractHoster(item.url) || ""; return <span key={col} className="pkg-col pkg-col-hoster" title={h}>{h}</span>; }
case "account": return <span key={col} className="pkg-col pkg-col-account">{item.providerLabel || (item.provider ? providerLabels[item.provider] : "")}</span>;
case "prio": return <span key={col} className="pkg-col pkg-col-prio"></span>;
case "status": return (
<span key={col} className="pkg-col pkg-col-status" title={statusTitle}>
case "status": {
const displayStatus = computeDisplayedItemStatus(item, sessionRunning);
const title = !displayStatus ? "" : (item.retries > 0 ? `${displayStatus} ? R${item.retries}` : displayStatus);
return (
<span key={col} className="pkg-col pkg-col-status" title={title}>
{displayStatus}
</span>
);
}
case "speed": return <span key={col} className="pkg-col pkg-col-speed">{item.speedBps > 0 ? formatSpeedMbps(item.speedBps) : ""}</span>;
case "added": return <span key={col} className="pkg-col pkg-col-added">{formattedCreatedAt}</span>;
case "added": return <span key={col} className="pkg-col pkg-col-added">{formatDateTime(item.createdAt)}</span>;
default: return null;
}
})}