From 32099095f796e057ca6f2965bbb494c193a1490d Mon Sep 17 00:00:00 2001 From: "Stiliyan Tonev (Bark)" Date: Tue, 17 Jun 2025 17:35:48 +0300 Subject: [PATCH 1/2] feat: Introduce 'By Shown File Order' priority in WebUI --- src/webui/www/private/index.html | 1 + src/webui/www/private/scripts/file-tree.js | 3 +- src/webui/www/private/scripts/prop-files.js | 52 ++++++++++++++++++++- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/webui/www/private/index.html b/src/webui/www/private/index.html index e10762d5f..8a823c397 100644 --- a/src/webui/www/private/index.html +++ b/src/webui/www/private/index.html @@ -269,6 +269,7 @@
  • QBT_TR(Normal)QBT_TR[CONTEXT=PropListDelegate]
  • QBT_TR(High)QBT_TR[CONTEXT=PropListDelegate]
  • QBT_TR(Maximum)QBT_TR[CONTEXT=PropListDelegate]
  • +
  • QBT_TR(By shown file order)QBT_TR[CONTEXT=PropListDelegate]
  • diff --git a/src/webui/www/private/scripts/file-tree.js b/src/webui/www/private/scripts/file-tree.js index c56ddeaef..234f2b1a0 100644 --- a/src/webui/www/private/scripts/file-tree.js +++ b/src/webui/www/private/scripts/file-tree.js @@ -45,7 +45,8 @@ window.qBittorrent.FileTree ??= (() => { Normal: 1, High: 6, Maximum: 7, - Mixed: -1 + Mixed: -1, + ByShownOrder: -2 }; Object.freeze(FilePriority); diff --git a/src/webui/www/private/scripts/prop-files.js b/src/webui/www/private/scripts/prop-files.js index b0242a9aa..e4ee789eb 100644 --- a/src/webui/www/private/scripts/prop-files.js +++ b/src/webui/www/private/scripts/prop-files.js @@ -478,7 +478,54 @@ window.qBittorrent.PropFiles ??= (() => { }); } - setFilePriority(Object.keys(uniqueRowIds), Object.keys(uniqueFileIds), priority); + // Will be used both in general case and ByShownOrder case + const filesLen = Object.keys(uniqueFileIds).length; + const priorityList = {}; + Object.values(FilePriority).forEach((p) => { + priorityList[p] = []; + }); + const priorityGroupSize = Math.max(Math.floor(filesLen / 3), 1); + const uniqueFileKeys = Object.keys(uniqueFileIds); + const uniqueRowKeys = Object.keys(uniqueRowIds); + + // Will be altered only if we select ByShownOrder, use whatever is passed otherwise + let priorityGroup = priority; + let fileId = 0; + let rowId = 0; + for (let i = 0; i < filesLen; ++i) { + fileId = uniqueFileKeys[i]; + rowId = uniqueRowKeys[i]; + // Calculate priority based on order + if (priority === FilePriority.ByShownOrder) { + switch (Math.floor(i / priorityGroupSize)) { + case 0: + priorityGroup = FilePriority.Maximum; + break; + case 1: + priorityGroup = FilePriority.High; + break; + default: + case 2: + priorityGroup = FilePriority.Normal; + break; + } + } + // Or if we use one of the simpler priorities, just push in the same group + priorityList[priorityGroup].push({ + fileId: fileId, + rowId: rowId + }); + } + + Object.entries(priorityList).forEach(([groupPriority, groupedFileRowPair]) => { + if (groupedFileRowPair.length === 0) + return; + setFilePriority( + groupedFileRowPair.map(pair => pair.rowId), + groupedFileRowPair.map(pair => pair.fileId), + groupPriority + ); + }); }; const singleFileRename = (hash) => { @@ -553,6 +600,9 @@ window.qBittorrent.PropFiles ??= (() => { }, FilePrioMaximum: (element, ref) => { filesPriorityMenuClicked(FilePriority.Maximum); + }, + FilePrioByShownOrder: (element, ref) => { + filesPriorityMenuClicked(FilePriority.ByShownOrder); } }, offsets: { From 35b94986b3b4d6d63dcde3fb7b3c765dc90a0b89 Mon Sep 17 00:00:00 2001 From: "Stiliyan Tonev (Bark)" Date: Mon, 23 Jun 2025 14:16:49 +0300 Subject: [PATCH 2/2] refact: Improve JS priority change logic --- src/webui/www/private/scripts/dynamicTable.js | 8 -- src/webui/www/private/scripts/file-tree.js | 3 +- src/webui/www/private/scripts/prop-files.js | 79 ++++++++----------- 3 files changed, 32 insertions(+), 58 deletions(-) diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index bb4492a86..35a6cb665 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -3044,14 +3044,6 @@ window.qBittorrent.DynamicTable ??= (() => { return rows; } - setIgnored(rowId, ignore) { - const row = this.rows.get(rowId.toString()); - if (ignore) - row.full_data.remaining = 0; - else - row.full_data.remaining = (row.full_data.size * (1.0 - (row.full_data.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 234f2b1a0..c56ddeaef 100644 --- a/src/webui/www/private/scripts/file-tree.js +++ b/src/webui/www/private/scripts/file-tree.js @@ -45,8 +45,7 @@ window.qBittorrent.FileTree ??= (() => { Normal: 1, High: 6, Maximum: 7, - Mixed: -1, - ByShownOrder: -2 + Mixed: -1 }; Object.freeze(FilePriority); diff --git a/src/webui/www/private/scripts/prop-files.js b/src/webui/www/private/scripts/prop-files.js index e4ee789eb..a5e0eac71 100644 --- a/src/webui/www/private/scripts/prop-files.js +++ b/src/webui/www/private/scripts/prop-files.js @@ -47,6 +47,7 @@ window.qBittorrent.PropFiles ??= (() => { const TriState = window.qBittorrent.FileTree.TriState; let is_seed = true; let current_hash = ""; + const BY_SHOWN_ORDER = -2; const normalizePriority = (priority) => { switch (priority) { @@ -105,7 +106,7 @@ window.qBittorrent.PropFiles ??= (() => { const rows = getAllChildren(id, fileId); - setFilePriority(rows.rowIds, rows.fileIds, priority); + setFilePriority(rows.fileIds, priority); updateGlobalCheckbox(); }; @@ -117,7 +118,7 @@ window.qBittorrent.PropFiles ??= (() => { const rows = getAllChildren(id, fileId); - setFilePriority(rows.rowIds, rows.fileIds, priority); + setFilePriority(rows.fileIds, priority); updateGlobalCheckbox(); }; @@ -241,7 +242,7 @@ window.qBittorrent.PropFiles ??= (() => { } if (rowIds.length > 0) - setFilePriority(rowIds, fileIds, priority); + setFilePriority(fileIds, priority); }; const updateGlobalCheckbox = () => { @@ -271,7 +272,7 @@ window.qBittorrent.PropFiles ??= (() => { checkbox.indeterminate = true; }; - const setFilePriority = (ids, fileIds, priority) => { + const setFilePriority = (fileIds, priority) => { if (current_hash === "") return; @@ -292,15 +293,6 @@ window.qBittorrent.PropFiles ??= (() => { loadTorrentFilesDataTimer = loadTorrentFilesData.delay(1000); }); - - const ignore = (priority === FilePriority.Ignored); - ids.forEach((id) => { - torrentFilesTable.setIgnored(id, ignore); - - const combobox = document.getElementById(`comboPrio${id}`); - if (combobox !== null) - selectComboboxPriority(combobox, priority); - }); }; let loadTorrentFilesDataTimer = -1; @@ -459,44 +451,40 @@ window.qBittorrent.PropFiles ??= (() => { if (selectedRows.length === 0) return; - const rowIds = []; const fileIds = []; + const fillInChildren = (rowId, fileId) => { + const children = getAllChildren(rowId, fileId); + children.fileIds.forEach((childFileId, index) => { + if (fileId === -1) { + fillInChildren(children.rowIds[index], childFileId); + return; + } + if (!fileIds.includes(childFileId)) + fileIds.push(childFileId); + }); + }; + selectedRows.forEach((rowId) => { - rowIds.push(rowId); - fileIds.push(torrentFilesTable.getRowFileId(rowId)); + const fileId = torrentFilesTable.getRowFileId(rowId); + if (fileId !== -1) + fileIds.push(fileId); + fillInChildren(rowId, fileId); }); - const uniqueRowIds = {}; - const uniqueFileIds = {}; - for (let i = 0; i < rowIds.length; ++i) { - const rows = getAllChildren(rowIds[i], fileIds[i]); - rows.rowIds.forEach((rowId) => { - uniqueRowIds[rowId] = true; - }); - rows.fileIds.forEach((fileId) => { - uniqueFileIds[fileId] = true; - }); - } - // Will be used both in general case and ByShownOrder case - const filesLen = Object.keys(uniqueFileIds).length; const priorityList = {}; Object.values(FilePriority).forEach((p) => { priorityList[p] = []; }); - const priorityGroupSize = Math.max(Math.floor(filesLen / 3), 1); - const uniqueFileKeys = Object.keys(uniqueFileIds); - const uniqueRowKeys = Object.keys(uniqueRowIds); + const groupsNum = 3; + const priorityGroupSize = Math.max(Math.floor(fileIds.length / groupsNum), 1); // Will be altered only if we select ByShownOrder, use whatever is passed otherwise let priorityGroup = priority; let fileId = 0; - let rowId = 0; - for (let i = 0; i < filesLen; ++i) { - fileId = uniqueFileKeys[i]; - rowId = uniqueRowKeys[i]; - // Calculate priority based on order - if (priority === FilePriority.ByShownOrder) { + for (let i = 0; i < fileIds.length; ++i) { + fileId = fileIds[i]; + if (priority === BY_SHOWN_ORDER) { switch (Math.floor(i / priorityGroupSize)) { case 0: priorityGroup = FilePriority.Maximum; @@ -510,19 +498,14 @@ window.qBittorrent.PropFiles ??= (() => { break; } } - // Or if we use one of the simpler priorities, just push in the same group - priorityList[priorityGroup].push({ - fileId: fileId, - rowId: rowId - }); + priorityList[priorityGroup].push(fileId); } - Object.entries(priorityList).forEach(([groupPriority, groupedFileRowPair]) => { - if (groupedFileRowPair.length === 0) + Object.entries(priorityList).forEach(([groupPriority, groupedFiles]) => { + if (groupedFiles.length === 0) return; setFilePriority( - groupedFileRowPair.map(pair => pair.rowId), - groupedFileRowPair.map(pair => pair.fileId), + groupedFiles, groupPriority ); }); @@ -602,7 +585,7 @@ window.qBittorrent.PropFiles ??= (() => { filesPriorityMenuClicked(FilePriority.Maximum); }, FilePrioByShownOrder: (element, ref) => { - filesPriorityMenuClicked(FilePriority.ByShownOrder); + filesPriorityMenuClicked(BY_SHOWN_ORDER); } }, offsets: {