mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-20 21:33:27 -07:00
Avoid duplicating torrent content data in table
All content data is already stored in the FileTree, so we now read from that data directly. We no longer store a second copy of this data in the TorrentFilesTable.
This commit is contained in:
parent
b2d6323034
commit
74a3d5bf76
3 changed files with 93 additions and 104 deletions
|
@ -993,9 +993,13 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
}
|
||||
}
|
||||
|
||||
getRowData(row, fullUpdate) {
|
||||
return row[fullUpdate ? "full_data" : "data"];
|
||||
}
|
||||
|
||||
updateRow(tr, fullUpdate) {
|
||||
const row = this.rows.get(tr.rowId);
|
||||
const data = row[fullUpdate ? "full_data" : "data"];
|
||||
const data = this.getRowData(row, fullUpdate);
|
||||
|
||||
const tds = this.getRowCells(tr);
|
||||
for (let i = 0; i < this.columns.length; ++i) {
|
||||
|
@ -1007,7 +1011,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
if (this.columns[i].dataProperties.some(prop => Object.hasOwn(data, prop)))
|
||||
this.columns[i].updateTd(tds[i], row);
|
||||
}
|
||||
row["data"] = {};
|
||||
row.data = {};
|
||||
}
|
||||
|
||||
removeRow(rowId) {
|
||||
|
@ -2358,25 +2362,9 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
node.depth = depth;
|
||||
node.parent = parent;
|
||||
|
||||
if (node.isFolder) {
|
||||
const data = {
|
||||
rowId: node.rowId,
|
||||
fileId: -1,
|
||||
checked: node.checked,
|
||||
path: node.path,
|
||||
original: node.original,
|
||||
renamed: node.renamed
|
||||
};
|
||||
|
||||
node.data = data;
|
||||
node.full_data = data;
|
||||
this.updateRowData(data);
|
||||
}
|
||||
else {
|
||||
node.data.rowId = node.rowId;
|
||||
node.full_data = node.data;
|
||||
this.updateRowData(node.data);
|
||||
}
|
||||
this.updateRowData({
|
||||
rowId: node.rowId
|
||||
});
|
||||
|
||||
node.children.each((child) => {
|
||||
this.#addNodeToTable(child, depth + 1, node);
|
||||
|
@ -2396,6 +2384,10 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
return this.rows.get(rowId);
|
||||
}
|
||||
|
||||
getRowData(row, fullUpdate) {
|
||||
return this.getNode(row.rowId);
|
||||
}
|
||||
|
||||
getSelectedRows() {
|
||||
const nodes = this.fileTree.toArray();
|
||||
|
||||
|
@ -2437,10 +2429,8 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
}
|
||||
|
||||
const nodes = this.fileTree.toArray();
|
||||
for (const node of nodes) {
|
||||
for (const node of nodes)
|
||||
node.checked = (checkbox.checked || checkbox.indeterminate) ? 0 : 1;
|
||||
node.full_data.checked = node.checked;
|
||||
}
|
||||
|
||||
this.updateGlobalCheckbox();
|
||||
}
|
||||
|
@ -2448,7 +2438,6 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
toggleNodeTreeCheckbox(rowId, checkState) {
|
||||
const node = this.getNode(rowId);
|
||||
node.checked = checkState;
|
||||
node.full_data.checked = checkState;
|
||||
const checkbox = document.getElementById(`cbRename${rowId}`);
|
||||
checkbox.checked = node.checked === 0;
|
||||
checkbox.state = checkbox.checked ? "checked" : "unchecked";
|
||||
|
@ -2530,7 +2519,6 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
for (const id of ids) {
|
||||
const node = that.getNode(id);
|
||||
node.checked = e.target.checked ? 0 : 1;
|
||||
node.full_data.checked = node.checked;
|
||||
}
|
||||
that.updateGlobalCheckbox();
|
||||
that.onRowSelectionChange(that.getNode(targetId));
|
||||
|
@ -2592,6 +2580,13 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
span.id = fileNameRenamedId;
|
||||
span.textContent = node.renamed;
|
||||
};
|
||||
|
||||
for (const column of this.columns) {
|
||||
column["getRowValue"] = function(row, pos = 0) {
|
||||
const node = that.getNode(row.rowId);
|
||||
return node[this.dataProperties[pos]];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
onRowSelectionChange(row) {}
|
||||
|
@ -2604,7 +2599,6 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
if (rowIds.includes(tr.rowId)) {
|
||||
const node = this.getNode(tr.rowId);
|
||||
node.checked = 0;
|
||||
node.full_data.checked = 0;
|
||||
|
||||
const checkbox = tr.querySelector(".RenamingCB");
|
||||
checkbox.state = "checked";
|
||||
|
@ -2623,18 +2617,16 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
while (stack.length > 0) {
|
||||
const node = stack.pop();
|
||||
|
||||
node.children.sort((row1, row2) => {
|
||||
node.children.sort((node1, node2) => {
|
||||
// list folders before files when sorting by name
|
||||
if (isColumnOriginal) {
|
||||
const node1 = this.getNode(row1.data.rowId);
|
||||
const node2 = this.getNode(row2.data.rowId);
|
||||
if (node1.isFolder && !node2.isFolder)
|
||||
return -1;
|
||||
if (!node1.isFolder && node2.isFolder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
const result = column.compareRows(row1, row2);
|
||||
const result = column.compareRows(node1, node2);
|
||||
return isReverseSort ? result : -result;
|
||||
});
|
||||
|
||||
|
@ -2746,14 +2738,6 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
return rows;
|
||||
}
|
||||
|
||||
setIgnored(rowId, ignore) {
|
||||
const row = this.rows.get(rowId);
|
||||
if (ignore)
|
||||
row.full_data.remaining = 0;
|
||||
else
|
||||
row.full_data.remaining = (row.full_data.size * (1.0 - (row.full_data.progress / 100)));
|
||||
}
|
||||
|
||||
setupCommonEvents() {
|
||||
const headerDiv = document.getElementById("bulkRenameFilesTableFixedHeaderDiv");
|
||||
this.dynamicTableDiv.addEventListener("scroll", (e) => {
|
||||
|
@ -2876,11 +2860,11 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
}
|
||||
|
||||
isAllCheckboxesChecked() {
|
||||
return this.fileTree.toArray().every((node) => node.checked === 1);
|
||||
return this.fileTree.toArray().every((node) => node.checked === window.qBittorrent.FileTree.TriState.Checked);
|
||||
}
|
||||
|
||||
isAllCheckboxesUnchecked() {
|
||||
return this.fileTree.toArray().every((node) => node.checked !== 1);
|
||||
return this.fileTree.toArray().every((node) => node.checked !== window.qBittorrent.FileTree.TriState.Checked);
|
||||
}
|
||||
|
||||
populateTable(root) {
|
||||
|
@ -2894,30 +2878,12 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
node.depth = depth;
|
||||
node.parent = parent;
|
||||
|
||||
if (node.isFolder) {
|
||||
if (!this.collapseState.has(node.rowId))
|
||||
if (node.isFolder && !this.collapseState.has(node.rowId))
|
||||
this.collapseState.set(node.rowId, { depth: depth, collapsed: false });
|
||||
const data = {
|
||||
rowId: node.rowId,
|
||||
size: node.size,
|
||||
checked: node.checked,
|
||||
remaining: node.remaining,
|
||||
progress: node.progress,
|
||||
priority: window.qBittorrent.TorrentContent.normalizePriority(node.priority),
|
||||
availability: node.availability,
|
||||
fileId: -1,
|
||||
name: node.name
|
||||
};
|
||||
|
||||
node.data = data;
|
||||
node.full_data = data;
|
||||
this.updateRowData(data, depth);
|
||||
}
|
||||
else {
|
||||
node.data.rowId = node.rowId;
|
||||
node.full_data = node.data;
|
||||
this.updateRowData(node.data);
|
||||
}
|
||||
this.updateRowData({
|
||||
rowId: node.rowId,
|
||||
});
|
||||
|
||||
node.children.each((child) => {
|
||||
this.#addNodeToTable(child, depth + 1, node);
|
||||
|
@ -2938,8 +2904,12 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
}
|
||||
|
||||
getRowFileId(rowId) {
|
||||
const row = this.rows.get(rowId);
|
||||
return row?.full_data.fileId;
|
||||
const node = this.getNode(rowId);
|
||||
return node.fileId;
|
||||
}
|
||||
|
||||
getRowData(row, fullUpdate) {
|
||||
return this.getNode(row.rowId);
|
||||
}
|
||||
|
||||
initColumns() {
|
||||
|
@ -2971,6 +2941,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
this.columns["checked"].updateTd = function(td, row) {
|
||||
const id = row.rowId;
|
||||
const value = this.getRowValue(row);
|
||||
const fileId = that.getRowFileId(id);
|
||||
|
||||
if (td.firstElementChild === null) {
|
||||
const treeImg = document.createElement("img");
|
||||
|
@ -2981,9 +2952,9 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
|
||||
const downloadCheckbox = td.children[1];
|
||||
if (downloadCheckbox === undefined)
|
||||
td.append(window.qBittorrent.TorrentContent.createDownloadCheckbox(id, row.full_data.fileId, value));
|
||||
td.append(window.qBittorrent.TorrentContent.createDownloadCheckbox(id, fileId, value));
|
||||
else
|
||||
window.qBittorrent.TorrentContent.updateDownloadCheckbox(downloadCheckbox, id, row.full_data.fileId, value);
|
||||
window.qBittorrent.TorrentContent.updateDownloadCheckbox(downloadCheckbox, id, fileId, value);
|
||||
|
||||
};
|
||||
this.columns["checked"].staticWidth = 50;
|
||||
|
@ -3072,12 +3043,13 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
this.columns["priority"].updateTd = function(td, row) {
|
||||
const id = row.rowId;
|
||||
const value = this.getRowValue(row);
|
||||
const fileId = that.getRowFileId(id);
|
||||
|
||||
const priorityCombo = td.firstElementChild;
|
||||
if (priorityCombo === null)
|
||||
td.append(window.qBittorrent.TorrentContent.createPriorityCombo(id, row.full_data.fileId, value));
|
||||
td.append(window.qBittorrent.TorrentContent.createPriorityCombo(id, fileId, value));
|
||||
else
|
||||
window.qBittorrent.TorrentContent.updatePriorityCombo(priorityCombo, id, row.full_data.fileId, value);
|
||||
window.qBittorrent.TorrentContent.updatePriorityCombo(priorityCombo, id, fileId, value);
|
||||
};
|
||||
this.columns["priority"].staticWidth = 140;
|
||||
|
||||
|
@ -3086,6 +3058,13 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
this.columns["remaining"].updateTd = displaySize;
|
||||
if (this.columns["availability"] !== undefined)
|
||||
this.columns["availability"].updateTd = displayPercentage;
|
||||
|
||||
for (const column of this.columns) {
|
||||
column["getRowValue"] = function(row, pos = 0) {
|
||||
const node = that.getNode(row.rowId);
|
||||
return node[this.dataProperties[pos]];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#sortNodesByColumn(root, column) {
|
||||
|
@ -3096,18 +3075,16 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
while (stack.length > 0) {
|
||||
const node = stack.pop();
|
||||
|
||||
node.children.sort((row1, row2) => {
|
||||
node.children.sort((node1, node2) => {
|
||||
// list folders before files when sorting by name
|
||||
if (isColumnName) {
|
||||
const node1 = this.getNode(row1.data.rowId);
|
||||
const node2 = this.getNode(row2.data.rowId);
|
||||
if (node1.isFolder && !node2.isFolder)
|
||||
return -1;
|
||||
if (!node1.isFolder && node2.isFolder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
const result = column.compareRows(row1, row2);
|
||||
const result = column.compareRows(node1, node2);
|
||||
return isReverseSort ? result : -result;
|
||||
});
|
||||
|
||||
|
@ -3177,8 +3154,8 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
|
||||
const generateRowsSignature = () => {
|
||||
const rowsData = [];
|
||||
for (const { full_data } of this.getRowValues())
|
||||
rowsData.push({ ...full_data, collapsed: this.isCollapsed(full_data.rowId) });
|
||||
for (const { rowId } of this.getRowValues())
|
||||
rowsData.push({ ...this.getNode(rowId).serialize(), collapsed: this.isCollapsed(rowId) });
|
||||
return JSON.stringify(rowsData);
|
||||
};
|
||||
|
||||
|
@ -3212,11 +3189,11 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
}
|
||||
|
||||
setIgnored(rowId, ignore) {
|
||||
const row = this.rows.get(rowId.toString());
|
||||
const node = this.getNode(rowId.toString());
|
||||
if (ignore)
|
||||
row.full_data.remaining = 0;
|
||||
node.remaining = 0;
|
||||
else
|
||||
row.full_data.remaining = (row.full_data.size * (1.0 - (row.full_data.progress / 100)));
|
||||
node.remaining = (node.size * (1.0 - (node.progress / 100)));
|
||||
}
|
||||
|
||||
setupCommonEvents() {
|
||||
|
|
|
@ -114,6 +114,7 @@ window.qBittorrent.FileTree ??= (() => {
|
|||
name = "";
|
||||
path = "";
|
||||
rowId = null;
|
||||
fileId = null;
|
||||
size = 0;
|
||||
checked = TriState.Unchecked;
|
||||
remaining = 0;
|
||||
|
@ -122,9 +123,22 @@ window.qBittorrent.FileTree ??= (() => {
|
|||
availability = 0;
|
||||
depth = 0;
|
||||
root = null;
|
||||
data = null;
|
||||
isFolder = false;
|
||||
children = [];
|
||||
|
||||
serialize() {
|
||||
return {
|
||||
name: this.name,
|
||||
path: this.path,
|
||||
fileId: this.fileId,
|
||||
size: this.size,
|
||||
checked: this.checked,
|
||||
remaining: this.remaining,
|
||||
progress: this.progress,
|
||||
priority: this.priority,
|
||||
availability: this.availability
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class FolderNode extends FileNode {
|
||||
|
@ -133,6 +147,7 @@ window.qBittorrent.FileTree ??= (() => {
|
|||
*/
|
||||
autoCheckFolders = true;
|
||||
isFolder = true;
|
||||
fileId = -1;
|
||||
|
||||
addChild(node) {
|
||||
this.children.push(node);
|
||||
|
|
|
@ -84,12 +84,12 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
|
||||
const getAllChildren = (id, fileId) => {
|
||||
const node = torrentFilesTable.getNode(id);
|
||||
const rowIds = [node.data.rowId];
|
||||
const fileIds = [node.data.fileId];
|
||||
const rowIds = [node.rowId];
|
||||
const fileIds = [node.fileId];
|
||||
|
||||
const getChildFiles = (node) => {
|
||||
rowIds.push(node.data.rowId);
|
||||
fileIds.push(node.data.fileId);
|
||||
rowIds.push(node.rowId);
|
||||
fileIds.push(node.fileId);
|
||||
|
||||
if (node.isFolder) {
|
||||
node.children.forEach((child) => {
|
||||
|
@ -214,8 +214,8 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
};
|
||||
|
||||
const getComboboxPriority = (id) => {
|
||||
const row = torrentFilesTable.rows.get(id.toString());
|
||||
return normalizePriority(row.full_data.priority, 10);
|
||||
const node = torrentFilesTable.getNode(id.toString());
|
||||
return normalizePriority(node.priority, 10);
|
||||
};
|
||||
|
||||
const switchGlobalCheckboxState = (e) => {
|
||||
|
@ -230,8 +230,9 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
setCheckboxUnchecked(checkbox);
|
||||
torrentFilesTable.rows.forEach((row) => {
|
||||
const rowId = row.rowId;
|
||||
const fileId = row.full_data.fileId;
|
||||
const isChecked = (getCheckboxState(rowId) === TriState.Checked);
|
||||
const node = torrentFilesTable.getNode(rowId);
|
||||
const fileId = node.fileId;
|
||||
const isChecked = (node.checked === TriState.Checked);
|
||||
if (isChecked) {
|
||||
rowIds.push(rowId);
|
||||
fileIds.push(fileId);
|
||||
|
@ -242,8 +243,9 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
setCheckboxChecked(checkbox);
|
||||
torrentFilesTable.rows.forEach((row) => {
|
||||
const rowId = row.rowId;
|
||||
const fileId = row.full_data.fileId;
|
||||
const isUnchecked = (getCheckboxState(rowId) === TriState.Unchecked);
|
||||
const node = torrentFilesTable.getNode(rowId);
|
||||
const fileId = node.fileId;
|
||||
const isUnchecked = (node.checked === TriState.Unchecked);
|
||||
if (isUnchecked) {
|
||||
rowIds.push(rowId);
|
||||
fileIds.push(fileId);
|
||||
|
@ -285,11 +287,6 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
checkbox.indeterminate = true;
|
||||
};
|
||||
|
||||
const getCheckboxState = (id) => {
|
||||
const row = torrentFilesTable.rows.get(id.toString());
|
||||
return Number(row.full_data.checked);
|
||||
};
|
||||
|
||||
const setFilePriority = (ids, fileIds, priority) => {
|
||||
priority = normalizePriority(priority);
|
||||
|
||||
|
@ -301,9 +298,9 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
id = id.toString();
|
||||
torrentFilesTable.setIgnored(id, ignore);
|
||||
|
||||
const row = torrentFilesTable.rows.get(id);
|
||||
row.full_data.priority = priority;
|
||||
row.full_data.checked = triStateFromPriority(priority);
|
||||
const node = torrentFilesTable.getNode(id);
|
||||
node.priority = priority;
|
||||
node.checked = triStateFromPriority(priority);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -377,6 +374,7 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
childNode.name = row.name;
|
||||
childNode.path = row.fileName;
|
||||
childNode.rowId = rowId;
|
||||
childNode.fileId = row.fileId;
|
||||
childNode.size = row.size;
|
||||
childNode.checked = isChecked;
|
||||
childNode.remaining = remaining;
|
||||
|
@ -384,7 +382,6 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
childNode.priority = row.priority;
|
||||
childNode.availability = row.availability;
|
||||
childNode.root = parent;
|
||||
childNode.data = row;
|
||||
parent.addChild(childNode);
|
||||
|
||||
++rowId;
|
||||
|
@ -447,7 +444,7 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
let indeterminateCount = 0;
|
||||
let desiredComboboxPriority = null;
|
||||
for (const sibling of siblings) {
|
||||
switch (getCheckboxState(sibling.rowId)) {
|
||||
switch (sibling.checked) {
|
||||
case TriState.Checked:
|
||||
++checkedCount;
|
||||
break;
|
||||
|
@ -465,7 +462,7 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
desiredComboboxPriority = FilePriority.Mixed;
|
||||
}
|
||||
|
||||
const currentCheckboxState = getCheckboxState(parent.rowId);
|
||||
const currentCheckboxState = parent.checked;
|
||||
let desiredCheckboxState = TriState.Unchecked;
|
||||
if ((indeterminateCount > 0) || ((checkedCount > 0) && (uncheckedCount > 0)))
|
||||
desiredCheckboxState = TriState.Partial;
|
||||
|
@ -474,9 +471,9 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||
|
||||
const currentComboboxPriority = getComboboxPriority(parent.rowId);
|
||||
if ((currentCheckboxState !== desiredCheckboxState) || (currentComboboxPriority !== desiredComboboxPriority)) {
|
||||
const row = torrentFilesTable.rows.get(parent.rowId.toString());
|
||||
row.full_data.priority = desiredComboboxPriority;
|
||||
row.full_data.checked = desiredCheckboxState;
|
||||
const node = torrentFilesTable.getNode(parent.rowId.toString());
|
||||
node.priority = desiredComboboxPriority;
|
||||
node.checked = desiredCheckboxState;
|
||||
|
||||
updateParentFolder(parent.rowId);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue