WebUI: migrate away from recursion

PR #22791.
This commit is contained in:
Chocobo1 2025-05-31 17:38:05 +08:00 committed by GitHub
parent a9213627a9
commit 4b07597d54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2476,27 +2476,51 @@ window.qBittorrent.DynamicTable ??= (() => {
});
}
#filterNodes(node, filterTerms, filteredRows) {
if (node.isFolder) {
const childAdded = node.children.reduce((acc, child) => {
// we must execute the function before ORing w/ acc or we'll stop checking child nodes after the first successful match
return (this.#filterNodes(child, filterTerms, filteredRows) || acc);
}, false);
#filterNodes(root, filterTerms) {
const ret = [];
const stack = [root];
const visited = [];
if (childAdded) {
const row = this.getRow(node);
filteredRows.push(row);
return true;
while (stack.length > 0) {
const node = stack.at(-1);
if (node.isFolder) {
const lastVisited = visited.at(-1);
if ((visited.length <= 0) || (lastVisited !== node)) {
visited.push(node);
stack.push(...node.children);
continue;
}
// has children added or itself matches
if (lastVisited.has_children_added || window.qBittorrent.Misc.containsAllTerms(node.name, filterTerms)) {
ret.push(this.getRow(node));
delete node.has_children_added;
// propagate up
const parent = node.root;
if (parent !== undefined)
parent.has_children_added = true;
}
visited.pop();
}
else {
if (window.qBittorrent.Misc.containsAllTerms(node.original, filterTerms)) {
ret.push(this.getRow(node));
const parent = node.root;
if (parent !== undefined)
parent.has_children_added = true;
}
}
stack.pop();
}
if (window.qBittorrent.Misc.containsAllTerms(node.original, filterTerms)) {
const row = this.getRow(node);
filteredRows.push(row);
return true;
}
return false;
ret.reverse();
return ret;
}
setFilter(text) {
@ -2518,22 +2542,15 @@ window.qBittorrent.DynamicTable ??= (() => {
return JSON.stringify(rowsData);
};
const getFilteredRows = function() {
const getFilteredRows = () => {
if (this.filterTerms.length === 0) {
const nodeArray = this.fileTree.toArray();
const filteredRows = nodeArray.map((node) => {
return this.getRow(node);
});
const filteredRows = nodeArray.map(node => this.getRow(node));
return filteredRows;
}
const filteredRows = [];
this.getRoot().children.each((child) => {
this.#filterNodes(child, this.filterTerms, filteredRows);
});
filteredRows.reverse();
return filteredRows;
}.bind(this);
return this.#filterNodes(this.getRoot().children[0], this.filterTerms);
};
const hasRowsChanged = function(rowsString, prevRowsStringString) {
const rowsChanged = (rowsString !== prevRowsStringString);
@ -2922,27 +2939,51 @@ window.qBittorrent.DynamicTable ??= (() => {
});
}
#filterNodes(node, filterTerms, filteredRows) {
if (node.isFolder && (!this.useVirtualList || !this.isCollapsed(node.rowId))) {
const childAdded = node.children.toReversed().reduce((acc, child) => {
// we must execute the function before ORing w/ acc or we'll stop checking child nodes after the first successful match
return (this.#filterNodes(child, filterTerms, filteredRows) || acc);
}, false);
#filterNodes(root, filterTerms) {
const ret = [];
const stack = [root];
const visited = [];
if (childAdded) {
const row = this.getRow(node);
filteredRows.push(row);
return true;
while (stack.length > 0) {
const node = stack.at(-1);
if (node.isFolder && (!this.useVirtualList || !this.isCollapsed(node.rowId))) {
const lastVisited = visited.at(-1);
if ((visited.length <= 0) || (lastVisited !== node)) {
visited.push(node);
stack.push(...node.children);
continue;
}
// has children added or itself matches
if (lastVisited.has_children_added || window.qBittorrent.Misc.containsAllTerms(node.name, filterTerms)) {
ret.push(this.getRow(node));
delete node.has_children_added;
// propagate up
const parent = node.root;
if (parent !== undefined)
parent.has_children_added = true;
}
visited.pop();
}
else {
if (window.qBittorrent.Misc.containsAllTerms(node.name, filterTerms)) {
ret.push(this.getRow(node));
const parent = node.root;
if (parent !== undefined)
parent.has_children_added = true;
}
}
stack.pop();
}
if (window.qBittorrent.Misc.containsAllTerms(node.name, filterTerms)) {
const row = this.getRow(node);
filteredRows.push(row);
return true;
}
return false;
ret.reverse();
return ret;
}
setFilter(text) {
@ -2964,14 +3005,7 @@ window.qBittorrent.DynamicTable ??= (() => {
return JSON.stringify(rowsData);
};
const getFilteredRows = function() {
const filteredRows = [];
this.getRoot().children.each((child) => {
this.#filterNodes(child, this.filterTerms, filteredRows);
});
filteredRows.reverse();
return filteredRows;
}.bind(this);
const getFilteredRows = () => this.#filterNodes(this.getRoot().children[0], this.filterTerms);
const hasRowsChanged = function(rowsString, prevRowsStringString) {
const rowsChanged = (rowsString !== prevRowsStringString);