diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index 9a8df230e..80f2e7a55 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -483,14 +483,10 @@ window.addEventListener("DOMContentLoaded", () => { } }; - const all = torrentsTable.getRowIds().length; + const all = torrentsTable.rows.size; let uncategorized = 0; - for (const key in torrentsTable.rows) { - if (!Object.hasOwn(torrentsTable.rows, key)) - continue; - - const row = torrentsTable.rows[key]; - if (row["full_data"].category.length === 0) + for (const { full_data: { category } } of torrentsTable.rows.values()) { + if (category.length === 0) uncategorized += 1; } @@ -585,12 +581,13 @@ window.addEventListener("DOMContentLoaded", () => { return tagFilterItem; }; - const torrentsCount = torrentsTable.getRowIds().length; + const torrentsCount = torrentsTable.rows.size; let untagged = 0; - for (const key in torrentsTable.rows) { - if (Object.hasOwn(torrentsTable.rows, key) && (torrentsTable.rows[key]["full_data"].tags.length === 0)) + for (const { full_data: { tags } } of torrentsTable.rows.values()) { + if (tags.length === 0) untagged += 1; } + tagFilterList.appendChild(createLink(TAGS_ALL, "QBT_TR(All)QBT_TR[CONTEXT=TagFilterModel]", torrentsCount)); tagFilterList.appendChild(createLink(TAGS_UNTAGGED, "QBT_TR(Untagged)QBT_TR[CONTEXT=TagFilterModel]", untagged)); @@ -637,13 +634,14 @@ window.addEventListener("DOMContentLoaded", () => { return trackerFilterItem; }; - const torrentsCount = torrentsTable.getRowIds().length; - trackerFilterList.appendChild(createLink(TRACKERS_ALL, "QBT_TR(All (%1))QBT_TR[CONTEXT=TrackerFiltersList]", torrentsCount)); + const torrentsCount = torrentsTable.rows.size; let trackerlessTorrentsCount = 0; - for (const key in torrentsTable.rows) { - if (Object.hasOwn(torrentsTable.rows, key) && (torrentsTable.rows[key]["full_data"].trackers_count === 0)) + for (const { full_data: { trackers_count: trackersCount } } of torrentsTable.rows.values()) { + if (trackersCount === 0) trackerlessTorrentsCount += 1; } + + trackerFilterList.appendChild(createLink(TRACKERS_ALL, "QBT_TR(All (%1))QBT_TR[CONTEXT=TrackerFiltersList]", torrentsCount)); trackerFilterList.appendChild(createLink(TRACKERS_TRACKERLESS, "QBT_TR(Trackerless (%1))QBT_TR[CONTEXT=TrackerFiltersList]", trackerlessTorrentsCount)); // Sort trackers by hostname diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index 395e81814..e039dfbd1 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -898,6 +898,11 @@ window.qBittorrent.DynamicTable ??= (() => { const TorrentsTable = new Class({ Extends: DynamicTable, + setup: function(dynamicTableDivId, dynamicTableFixedHeaderDivId, contextMenu) { + this.parent(dynamicTableDivId, dynamicTableFixedHeaderDivId, contextMenu); + this.rows = new Map(); + }, + initColumns: function() { this.newColumn("priority", "", "#", 30, true); this.newColumn("state_icon", "cursor: default", "", 22, true); @@ -1504,12 +1509,30 @@ window.qBittorrent.DynamicTable ??= (() => { return true; }, + removeRow: function(rowId) { + this.selectedRows.erase(rowId); + this.rows.delete(rowId); + const tr = this.getTrByRowId(rowId); + tr?.destroy(); + }, + + clear: function() { + this.deselectAll(); + this.rows.clear(); + const trs = this.tableBody.getElements("tr"); + while (trs.length > 0) + trs.pop().destroy(); + }, + + getRowIds: function() { + return this.rows.keys(); + }, + getFilteredTorrentsNumber: function(filterName, categoryHash, tagHash, trackerHash) { let cnt = 0; - const rows = this.rows.getValues(); - for (let i = 0; i < rows.length; ++i) { - if (this.applyFilter(rows[i], filterName, categoryHash, tagHash, trackerHash, null)) + for (const row of this.rows.values()) { + if (this.applyFilter(row, filterName, categoryHash, tagHash, trackerHash, null)) ++cnt; } return cnt; @@ -1517,11 +1540,10 @@ window.qBittorrent.DynamicTable ??= (() => { getFilteredTorrentsHashes: function(filterName, categoryHash, tagHash, trackerHash) { const rowsHashes = []; - const rows = this.rows.getValues(); - for (let i = 0; i < rows.length; ++i) { - if (this.applyFilter(rows[i], filterName, categoryHash, tagHash, trackerHash, null)) - rowsHashes.push(rows[i]["rowId"]); + for (const row of this.rows.values()) { + if (this.applyFilter(row, filterName, categoryHash, tagHash, trackerHash, null)) + rowsHashes.push(row["rowId"]); } return rowsHashes; @@ -1542,11 +1564,10 @@ window.qBittorrent.DynamicTable ??= (() => { return filteredRows; } - const rows = this.rows.getValues(); - for (let i = 0; i < rows.length; ++i) { - if (this.applyFilter(rows[i], selectedStatus, selectedCategory, selectedTag, selectedTracker, filterTerms)) { - filteredRows.push(rows[i]); - filteredRows[rows[i].rowId] = rows[i]; + for (const row of this.rows.values()) { + if (this.applyFilter(row, selectedStatus, selectedCategory, selectedTag, selectedTracker, filterTerms)) { + filteredRows.push(row); + filteredRows[row.rowId] = row; } } diff --git a/src/webui/www/private/scripts/mocha-init.js b/src/webui/www/private/scripts/mocha-init.js index fcf613c41..24ccdb332 100644 --- a/src/webui/www/private/scripts/mocha-init.js +++ b/src/webui/www/private/scripts/mocha-init.js @@ -295,7 +295,7 @@ const initializeWindows = function() { // check if all selected torrents have same share ratio for (let i = 0; i < hashes.length; ++i) { const hash = hashes[i]; - const row = torrentsTable.rows[hash].full_data; + const row = torrentsTable.rows.get(hash).full_data; const origValues = row.ratio_limit + "|" + row.seeding_time_limit + "|" + row.inactive_seeding_time_limit + "|" + row.max_ratio + "|" + row.max_seeding_time + "|" + row.max_inactive_seeding_time; @@ -522,7 +522,7 @@ const initializeWindows = function() { if (hashes.length) { let enable = false; hashes.each((hash, index) => { - const row = torrentsTable.rows[hash]; + const row = torrentsTable.rows.get(hash); if (!row.full_data.auto_tmm) enable = true; }); @@ -570,7 +570,7 @@ const initializeWindows = function() { const hashes = torrentsTable.selectedRowsIds(); if (hashes.length) { const hash = hashes[0]; - const row = torrentsTable.rows[hash]; + const row = torrentsTable.rows.get(hash); new MochaUI.Window({ id: "setLocationPage", @@ -593,7 +593,7 @@ const initializeWindows = function() { const hashes = torrentsTable.selectedRowsIds(); if (hashes.length === 1) { const hash = hashes[0]; - const row = torrentsTable.rows[hash]; + const row = torrentsTable.rows.get(hash); if (row) { new MochaUI.Window({ id: "renamePage", @@ -617,7 +617,7 @@ const initializeWindows = function() { const hashes = torrentsTable.selectedRowsIds(); if (hashes.length === 1) { const hash = hashes[0]; - const row = torrentsTable.rows[hash]; + const row = torrentsTable.rows.get(hash); if (row) { new MochaUI.Window({ id: "multiRenamePage",