From a7d10b4a916dc60bffe0273ed04a5ed72d5eeefd Mon Sep 17 00:00:00 2001 From: Thomas Piccirello Date: Sun, 8 Jun 2025 22:22:28 -0700 Subject: [PATCH] Recalculate remaining size when priority changes Previously, we would have to wait for the API to respond with updated values before updating the 'remaining' size of folders. This also centralizes all math related to `remaining` size in FileTree. --- src/webui/www/private/scripts/dynamicTable.js | 12 ++++------ src/webui/www/private/scripts/file-tree.js | 23 +++++++++++++++++-- .../www/private/scripts/torrent-content.js | 17 +++++++------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index 3fb778c22..b49f35a2f 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -2912,6 +2912,10 @@ window.qBittorrent.DynamicTable ??= (() => { return this.getNode(row.rowId); } + calculateRemaining() { + this.fileTree.getRoot().calculateRemaining(); + } + initColumns() { this.newColumn("checked", "", "", 50, true); this.newColumn("name", "", "QBT_TR(Name)QBT_TR[CONTEXT=TrackerListWidget]", 300, true); @@ -3188,14 +3192,6 @@ window.qBittorrent.DynamicTable ??= (() => { return rows; } - setIgnored(rowId, ignore) { - const node = this.getNode(rowId.toString()); - if (ignore) - node.remaining = 0; - else - node.remaining = (node.size * (1.0 - (node.progress / 100))); - } - setupCommonEvents() { super.setupCommonEvents(); this.dynamicTableDiv.addEventListener("keydown", (e) => { diff --git a/src/webui/www/private/scripts/file-tree.js b/src/webui/www/private/scripts/file-tree.js index 13bbf0488..4c4c32ed0 100644 --- a/src/webui/www/private/scripts/file-tree.js +++ b/src/webui/www/private/scripts/file-tree.js @@ -126,6 +126,14 @@ window.qBittorrent.FileTree ??= (() => { isFolder = false; children = []; + isIgnored() { + return this.priority === FilePriority.Ignored; + } + + calculateRemaining() { + this.remaining = this.isIgnored() ? 0 : (this.size * (1.0 - (this.progress / 100))); + } + serialize() { return { name: this.name, @@ -150,6 +158,7 @@ window.qBittorrent.FileTree ??= (() => { fileId = -1; addChild(node) { + node.calculateRemaining(); this.children.push(node); } @@ -196,8 +205,7 @@ window.qBittorrent.FileTree ??= (() => { root.checked = TriState.Partial; } - const isIgnored = (child.priority === FilePriority.Ignored); - if (!isIgnored) { + if (!child.isIgnored()) { root.remaining += child.remaining; root.progress += (child.progress * child.size); root.availability += (child.availability * child.size); @@ -212,6 +220,17 @@ window.qBittorrent.FileTree ??= (() => { stack.pop(); } } + + /** + * Recursively recalculate the amount of data remaining to be downloaded. + * This is useful for updating a folder's "remaining" size as files are unchecked/ignored. + */ + calculateRemaining() { + this.remaining = this.children.reduce((sum, node) => { + node.calculateRemaining(); + return sum + node.remaining; + }, 0); + } } return exports(); diff --git a/src/webui/www/private/scripts/torrent-content.js b/src/webui/www/private/scripts/torrent-content.js index 932b4ab94..37a216b96 100644 --- a/src/webui/www/private/scripts/torrent-content.js +++ b/src/webui/www/private/scripts/torrent-content.js @@ -293,15 +293,16 @@ window.qBittorrent.TorrentContent ??= (() => { if (onFilePriorityChanged) onFilePriorityChanged(fileIds, priority); - const ignore = (priority === FilePriority.Ignored); - ids.forEach((id) => { - id = id.toString(); - torrentFilesTable.setIgnored(id, ignore); - - const node = torrentFilesTable.getNode(id); + const nodes = ids.map((id) => { + const node = torrentFilesTable.getNode(id.toString()); node.priority = priority; node.checked = triStateFromPriority(priority); + return node; }); + + // must update all nodes above before recalculating + for (const node of nodes) + node.calculateRemaining(); }; const updateData = (files) => { @@ -315,7 +316,6 @@ window.qBittorrent.TorrentContent ??= (() => { size: file.size, progress: window.qBittorrent.Misc.toFixedPointString((file.progress * 100), 1), priority: normalizePriority(file.priority), - remaining: (ignore ? 0 : (file.size * (1 - file.progress))), availability: file.availability }; @@ -369,7 +369,6 @@ window.qBittorrent.TorrentContent ??= (() => { }); const isChecked = row.checked ? TriState.Checked : TriState.Unchecked; - const remaining = (row.priority === FilePriority.Ignored) ? 0 : row.remaining; const childNode = new window.qBittorrent.FileTree.FileNode(); childNode.name = row.name; childNode.path = row.fileName; @@ -377,7 +376,6 @@ window.qBittorrent.TorrentContent ??= (() => { childNode.fileId = row.fileId; childNode.size = row.size; childNode.checked = isChecked; - childNode.remaining = remaining; childNode.progress = row.progress; childNode.priority = row.priority; childNode.availability = row.availability; @@ -427,6 +425,7 @@ window.qBittorrent.TorrentContent ??= (() => { const updateComplete = () => { // we've finished recursing updateGlobalCheckbox(); + torrentFilesTable.calculateRemaining(); torrentFilesTable.updateTable(true); };