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:
Thomas Piccirello 2024-10-07 16:12:32 -07:00
commit 74a3d5bf76
No known key found for this signature in database
3 changed files with 93 additions and 104 deletions

View file

@ -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() {

View file

@ -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);

View file

@ -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);
}